如何在声音输入上触发振动?

Mom*_*omo 8 audio android vibration android-vibration mediarecorder

我正在尝试创建一个Android应用程序,我在其中过滤一个特定频率的蜂鸣声并使手机振动.

我从移动设备的MIC中获取输入并使用MediaRecorder类,通过使用这个类,我可以记录,保存和播放输入.现在,只要有哔哔声或任何声音,我就需要我的手机振动.

输入是通过电线给移动设备的耳机插孔,所以我知道只有一个频率输入.

我有一个按钮,点击开始录制.我已经拥有振动并在我的清单文件中记录的权限.

record.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    isRecording=true;
                    myAudioRecorder.prepare();
                    myAudioRecorder.start();
...
}
Run Code Online (Sandbox Code Playgroud)

我也尝试搜索互联网,在这里发现了类似的问题,但我找不到任何正确的答案.

但是,我可以点击另一个按钮让手机振动,这里是代码片段,

 Vibrator vibrate;
    vibrate = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

        Btn1.setOnClickListener(new View.OnClickListener()

                                {
                                    @Override
                                    public void onClick(View v) {
                                       vibrate.vibrate(800);
                                    }
                                }
Run Code Online (Sandbox Code Playgroud)

我试着在recorder.start()中调用一个振动器; 功能但这使手机即使在没有声音时也会振动.我也试过从这个问题得到帮助,所以每当有沉默,手机不应该振动,但我感到困惑,我知道应该有一个布尔值,当有声音并使手机振动时,它会变为真,但我我无法将此逻辑放入代码中.请让我知道在这种情况下我该怎么办?我应该在哪个方向搜索?

更新 我发现这个动作用于显示输入声音幅度的进度条,它工作正常,我试图让手机在缓冲区有一些值时振动,现在它振动甚至当振幅为零时,我猜那是因为事实上,每一次振动都会产生噪音,导致手机振动.由于java.lang.RuntimeException,我无法通过TOAST检查函数:无法在未调用Looper.prepare()的线程内创建处理程序.有什么建议吗?

Ric*_*rdo 6

对于您的主要问题,也许您可​​以检查声音的振幅,并且只有在达到最小阈值时才会振动.像这样的东西:

private class DetectAmplitude extends AsyncTask<Void, Void, Void> {

    private MediaRecorder mRecorder = null;
    private final static int MAX_AMPLITUDE = 32768;
    //TODO: Investigate what is the ideal value for this parameter
    private final static int MINIMUM_REQUIRED_AVERAGE = 5000;

    @Override
    protected Void doInBackground(Void... params) {
        Boolean soundStarted = true;
        if (mRecorder == null) {
            mRecorder = new MediaRecorder();
            mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
            mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
            mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
            mRecorder.setOutputFile("/dev/null");
            try {
                mRecorder.prepare();
            } catch (IllegalStateException e) {
                soundStarted = false;
                Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage());
            } catch (IOException e) {
                soundStarted = false;
                Log.e(TAG, "Could not detect background noise. Error preparing recorder: " + e.getMessage());
            }
            try {
                mRecorder.start();
            } catch (RuntimeException e) {
                Log.e(TAG, "Could not detect background noise. Error starting recorder: " + e.getMessage());
                soundStarted = false;
                mRecorder.release();
                mRecorder = null;
            }
        }

        if (soundStarted) {
            // Compute a simple average of the amplitude over one
            // second
            int nMeasures = 100;
            int sumAmpli = 0;
            mRecorder.getMaxAmplitude(); // First call returns 0
            int n = 0;
            for (int i = 0; i < nMeasures; i++) {
                if (mRecorder != null) {
                    int maxAmpli = mRecorder.getMaxAmplitude();
                    if (maxAmpli > 0) {
                        sumAmpli += maxAmpli;
                        n++;
                    }
                } else {
                    return null;
                }
                try {
                    Thread.sleep(1000 / nMeasures);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            mRecorder.stop();
            mRecorder.release();
            mRecorder = null;

            final float avgAmpli = (float) sumAmpli / n;

            if (avgAmpli > MINIMUM_REQUIRED_AVERAGE) {
                //TODO: Vibrate the device here
            }
        }
        return null;
    }
} 
Run Code Online (Sandbox Code Playgroud)

有关声级检测的更多信息,请参阅以下内容:

关于异常java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(),这是因为Toast需要在您的应用程序的主线程上运行.如果你的Thread代码(如a AsyncTask)在里面Activity,你可以尝试以下方法:

runOnUiThread(new Runnable() {
        @Override
        public void run() {
            //Call your Toast here
        }
    });
Run Code Online (Sandbox Code Playgroud)

否则,你需要以某种方式将你的方法的结论传递Activity给它来运行它Toast.

编辑:

如果你想使用这个从Button,你可以设置它OnClickListener在您ActivityonCreate()通话并执行AsyncTask那里.例如:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);
    Button button = (Button)findViewById(R.id.your_button_id);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new DetectAmplitude().execute(new Void[]{});
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

我建议您在生产代码中使用它之前先了解AsyncTask的工作原理.


小智 0

尝试这个:

Btn1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            v.post(new Runnable() {

                @Override
                public void run() {

                    vibrate.vibrate(800);
                }
            });

        }
    });
Run Code Online (Sandbox Code Playgroud)