如何在 android Pie 和 UP 中以编程方式打开/关闭扬声器

Posted

技术标签:

【中文标题】如何在 android Pie 和 UP 中以编程方式打开/关闭扬声器【英文标题】:how to turn speaker on/off programmatically in android Pie and UP 【发布时间】:2019-06-03 11:56:08 【问题描述】:

与这个问题以及几年前的许多其他问题相同: how to turn speaker on/off programmatically in android 4.0

Android 似乎改变了它处理这个问题的方式。

以下是我尝试以编程方式拨打电话以使用免提电话的方式。这些解决方案都不适用于 Android Pie。 虽然它们似乎在 Android Nougat 和 Oreo 上运行良好

解决方案 1。

final static int FOR_MEDIA = 1;
final static int FORCE_NONE = 0;
final static int FORCE_SPEAKER = 1;

Class audiosystemClass = Class.forName("android.media.AudioSystem");
Method setForceUse = audioSystemClass.getMethod("setForceUse", int.class, int.class);
setForceUse.invoke(null, FOR_MEDIA, FORCE_SPEAKER);

2.

AudioManager audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
if (audioManager != null) 
   audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
   audioManager.setSpeakerphoneOn(true);

3.

AudioManager audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
if (audioManager != null) 
   audioManager.setMode(AudioManager.MODE_IN_CALL);
   audioManager.setSpeakerphoneOn(true);

4.

Thread thread = new Thread() 
    @Override
    public void run() 
        try 
            while(true) 
                sleep(1000);
                audioManager.setMode(AudioManager.MODE_IN_CALL);
                if (!audioManager.isSpeakerphoneOn())
                    audioManager.setSpeakerphoneOn(true);
            
         catch (InterruptedException e) 
            e.printStackTrace();
        
    
;
thread.start();

该应用具有以下授予的许多其他权限:

<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />

我还尝试了以下仅用于拨出电话的解决方案。它也没有工作。

Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.putExtra("speaker", true);
callIntent.setData(Uri.parse("tel:" + number));
context.startActivity(callIntent);

【问题讨论】:

你是怎么解决这个问题的? M 在 oreo nd up 上面临同样的问题 问题尚未解决。 我有更多信息。在Android Pie中,该应用程序需要一个额外的权限,MODIFY_AUDIO_ROUTING,据我所知,这只能授予系统应用程序。如果您拥有此权限,解决方案 1 应该可以工作。 ndroidaudiotes:访问隐藏方法 Landroid/media/AudioSystem;->setForceUse(II)I(浅灰名单,反射)权限失败:android.permission.MODIFY_AUDIO_ROUTING from uid=10296 pid=26584 CALL_LOG 不能在 Android 9 中使用。 【参考方案1】:

在 Android Pie 中,我遇到了同样的问题。我使用带有

的InCallService 解决了它
setAudioRoute(ROUTE_SPEAKER)

您的应用需要是默认手机应用。

【讨论】:

有没有其他方法不做默认手机应用? 我尝试了许多不同的方法,但这是我发现的唯一可行的解​​决方案【参考方案2】:

我很惊讶没有人提到TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE。

作为一个意图:

val uri = Uri.fromParts("tel", PHONE_NUMBER, null)
val intentCall = Intent(Intent.ACTION_CALL, uri).apply 
    putExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true)
    flags = Intent.FLAG_ACTIVITY_NEW_TASK

startActivity(intentCall)

使用 TelecomManager.placeCall:

val uri = Uri.fromParts("tel", PHONE_NUMBER, null)
val extras = Bundle().apply  putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true) 
val telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
telecomManager.placeCall(uri, extras)

默认手机应用应处理这些额外数据并启用扬声器。

记得请求android.permission.CALL_PHONE的权限。

【讨论】:

在 Android 11 中为我工作【参考方案3】:

对于这个问题,请尝试下面的代码,它对我有用。

AudioManager myAudioManager;
myAudioManager.setMode(AudioManager.MODE_NORMAL);
myAudioManager.setSpeakerphoneOn(true);

【讨论】:

这并不能解决问题,这只会打开免提电话,而不是启用听筒而不是耳机。【参考方案4】:

在我的自我管理的语音通话应用程序中,我通过更改连接服务音频路由来管理,如下所示,除了使用 audioManager,

 public void setSpeakerphoneOn(final boolean enabled) 
            if (enabled != audioManager.isSpeakerphoneOn()) 
                Log.d(TAG, "setSpeakerphoneOn(): " + enabled);
                audioManager.setSpeakerphoneOn(enabled);
            
    

在我的连接服务类中,

   public void speakerOnOff(String uuid,boolean on) 
        Log.d(TAG,"SPEAKER  is" + String.valueOf(on));

        Connection connection = VoipConnectionService.getConnection(uuid);

        if (on) 
            connection.setAudioRoute(CallAudioState.ROUTE_SPEAKER);

         else 
            connection.setAudioRoute(CallAudioState.ROUTE_EARPIECE);
        


    

或者您可以根据您的音频设备更改路由以进行输出

public void speakerOnOff(String uuid,String device) 
     Log.d(TAG,"Device to  route  is" + device);

        Connection connection = VoipConnectionService.getConnection(uuid);

            int state =  CallAudioState.ROUTE_EARPIECE ;
            switch (device)
                case   "SPEAKER_PHONE":
                  state  = CallAudioState.ROUTE_SPEAKER ;
                  break;
                case "WIRED_HEADSET":
                    state  = CallAudioState.ROUTE_WIRED_HEADSET ;
                    break;
                case "EARPIECE" :
                case "NONE" :
                    state  = CallAudioState.ROUTE_EARPIECE ;
                    break;
                case "BLUETOOTH" :
                    state  = CallAudioState.ROUTE_BLUETOOTH ;
                    break;
            
            connection.setAudioRoute(state);
        

【讨论】:

以上是关于如何在 android Pie 和 UP 中以编程方式打开/关闭扬声器的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式获取 Android 手机型号,如何在 android 中以编程方式获取设备名称和型号?

如何在 Android 中以编程方式增加和减少音量

如何在 Android 10 中以编程方式安装任何 Android 应用

如何在 Android 中以编程方式设置按钮的边距?

如何在 Android 中以编程方式更改按钮大小?

如何在android中以编程方式设置ImageView的高度宽度?