ToneGenerator在安卓6.0上崩溃了。

4

在我的应用程序中,我使用ToneGenerator播放简单的声音。当我使用6.0编译应用程序进行测试时,由于ToneGenerator init方法,我的应用程序会随机崩溃。以下是异常情况。

 java.lang.RuntimeException: Init failed 
04-21 12:34:05.497  7166  7166 E MyApplication:     at android.media.ToneGenerator.native_setup(Native Method) 
04-21 12:34:05.497  7166  7166 E MyApplication:     at android.media.ToneGenerator.<init>(ToneGenerator.java:746)

我是以下面的方式使用音调发生器。

    public ToneGenerator toneGenerator;
    public void playSound() { 
       if (toneGenerator == null) {
          toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
        }
       toneGenerator.startTone(ToneGenerator.TONE_CDMA_ANSWER, 200);
   }


   public void releaseToneGenerator() {
      if (toneGenerator != null) {
        toneGenerator.release();
      }
    }

是否有人遇到了相同的问题?之前我的应用程序在4.4上运行,我们没有观察到任何崩溃。但是在6.0上应用程序崩溃了。


Naresh,你能否在调用startTone后立即尝试调用toneGenerator对象的release函数吗? - Nakul Sudhakar
2个回答

13

通过使用处理程序解决了这个问题。

private static void playTone(Context context, int mediaFileRawId) {
            Log.d(TAG, "playTone");
            try {
                if (toneGenerator == null) {
                    toneGenerator = new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100);
                }
                toneGenerator.startTone(mediaFileRawId, 200);
                Handler handler = new Handler(Looper.getMainLooper());
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (toneGenerator != null) {
                            Log.d(TAG, "ToneGenerator released");
                            toneGenerator.release();
                            toneGenerator = null;
                        }
                    }

                }, 200);
            } catch (Exception e) {
                Log.d(TAG, "Exception while playing sound:" + e);
            }
        }

这确实解决了我在我的Android 8.1 el-cheapo Redmi 6A上遇到的同样问题: java.lang.RuntimeException: Init failed at android.media.ToneGenerator.native_setup(Native Method) at android.media.ToneGenerator.<init>(ToneGenerator.java:746) at com.susu.mylib.core.MyRecognitionListener.<init>(MyRecognitionListener.java:176) at com.susu.mylib.core.MyActivity.startVoiceRecognitionActivity(MyActivity.java:1903) at com.susu.mylib.core.MyActivity$10.run(MyActivity.java:2287) at android.os.Handler.handleCallback(Handler.java:794) at android.os.Handler.dispatchMessage(Handler.java:99) - WebViewer

0
以下是基于音调发生器的解决方案,看起来很稳定,使用DialogFragment中的ontouch监听器。在OnViewCreated方法中为每个按钮设置onTouchListeners,然后使用以下ontouch监听器方法,在触摸按钮时连续播放所选的DTMF音调,当按钮不再被触摸时停止播放。AnswerDialogListener是回调到MainActivity的回调函数。
编辑:我尝试通过使用toneType = ToneGenerator.TONE_DTMF_0;而不是toneType = toneGenerator.TONE_DTMF_0;来修复编译器警告,结果破坏了之前正常工作的DTMF音调RFC2833输出。
private View.OnTouchListener myTouchListener = new View.OnTouchListener(){
    public boolean onTouch(View v, MotionEvent event) {
        String callidText = callid;
        AnswerDialogListener listener = (AnswerDialogListener) getActivity();
        int streamType = AudioManager.STREAM_MUSIC;
        int volume = 50;
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            switch (v.getId()) {
                case R.id.answer_dialog_0_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad0");
                    toneType = toneGenerator.TONE_DTMF_0;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_1_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad1");
                    toneType = toneGenerator.TONE_DTMF_1;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_2_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad2");
                    toneType = toneGenerator.TONE_DTMF_2;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_3_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad3");
                    toneType = toneGenerator.TONE_DTMF_3;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_4_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad4");
                    toneType = toneGenerator.TONE_DTMF_4;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_5_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad5");
                    toneType = toneGenerator.TONE_DTMF_5;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_6_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad6");
                    toneType = toneGenerator.TONE_DTMF_6;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_7_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad7");
                    toneType = toneGenerator.TONE_DTMF_7;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_8_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad8");
                    toneType = toneGenerator.TONE_DTMF_8;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_9_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "Keypad9");
                    toneType = toneGenerator.TONE_DTMF_9;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_asterisk_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "KeypadAsterisk");
                    toneType = toneGenerator.TONE_DTMF_S;
                    toneGenerator.startTone(toneType);
                    return true;
                case R.id.answer_dialog_hash_button:
                    toneGenerator = new ToneGenerator(streamType, volume);
                    toneGenerator.getAudioSessionId();
                    listener.onAnswerResponse(callidText, "KeypadHash");
                    toneType = toneGenerator.TONE_DTMF_P;
                    toneGenerator.startTone(toneType);
                    return true;
            }
        }
        if(event.getAction() == MotionEvent.ACTION_UP) {
            switch (v.getId()) {
                case R.id.answer_dialog_0_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_1_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_2_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_3_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_4_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_5_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_6_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_7_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_8_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_9_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_asterisk_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
                case R.id.answer_dialog_hash_button:
                    toneGenerator.stopTone();
                    toneGenerator.release();
                    return true;
            }
        }
        return false;
    }
};

以下是在MainActivity回调处理程序中的if语句片段,用于输出活动SIP呼叫上的DTMF:
if (response.equals("Keypad0")) {
            try {
                if (call != null) {
                    call.sendDtmf(0);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (response.equals("Keypad1")) {
            try {
                if (call != null) {
                    call.sendDtmf(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接