infinat 2019-08-26 19:26 采纳率: 0%
浏览 323

android 8.0以上如何用mediaButton控制来电接听?

1、需求描述
当来电时,用蓝牙发来的mediaButton KeyEvent,控制接听或者拒接

2、难点
如何在来电时能够获取MediaButton的事件

3、尝试1
通过AudioManager抢焦点、注册MediaButtonRecever,可以实现截获MediaButton KeyEvent
,通过监听焦点丢失,重复启动抢占焦点,也可以防止普通的APP抢去焦点。
但来电时,电话进程级别很高,根本抢不过来。所以此路不通

4、尝试2
后来发现Logcat中是有响应的KeyEvent日志的,比如一个Tag为MediaSessionService的,就会在蓝牙按键后,记录一个dispachKeyEvent日志。且不受来电、APP影响。于是尝试通过监听此Tag日志来实现需求。但不幸的是此日志可以在ADB命令中看到,但在APP中却无法读取。

5、求问
一是有没有办法实现需求(不root),
二是Logcat读取有权限和层级控制吗?

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-07-31 14:18
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    要使用Android MediaButton API来控制来电接听,您需要遵循以下步骤:

    步骤1: 配置MediaSession

    首先,确保您的应用已正确配置了MediaSession以接收媒体按钮事件。这可以通过设置<uses-permission android:name="android.permission.BLUETOOTH" />和在AndroidManifest.xml文件中添加<provider>标签来完成。

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.mediabuttondemo">
    
        <application
            android:name=".MainActivity">
            ...
        </application>
    </manifest>
    

    步骤2: 添加MediaButtonReceiver

    接下来,在您的应用中添加MediaButtonReceiver。这个类将负责处理MediaButton事件,并将其转发给相应的Activity或服务。

    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.media.session.MediaButtonReceiver;
    
    public class MyMediaButtonReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // 处理MediaButton事件
            handleMediaButtonEvent(intent);
        }
    
        private void handleMediaButtonEvent(Intent intent) {
            String action = intent.getAction();
            if (ACTION_MEDIA_BUTTON.equals(action)) {
                String mediaButtonCommand = intent.getStringExtra(MediaButtonReceiver.EXTRA_COMMAND);
                switch (mediaButtonCommand) {
                    case "accept":
                        acceptCall();
                        break;
                    case "decline":
                        declineCall();
                        break;
                    default:
                        System.out.println("Unknown command: " + mediaButtonCommand);
                }
            } else {
                System.out.println("Unknown action: " + action);
            }
        }
    
        private void acceptCall() {
            // 处理接受呼叫逻辑
        }
    
        private void declineCall() {
            // 处理拒绝呼叫逻辑
        }
    }
    

    步骤3: 注册MediaButtonReceiver

    确保您的应用程序在创建时注册MediaButtonReceiver。

    import android.app.Application;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.example.mediabuttondemo.R;
    import com.example.mediabuttondemo.databinding.ActivityMainBinding;
    import com.google.android.exoplayer2.ExoPlayerFactory;
    import com.google.android.exoplayer2.SimpleExoPlayer;
    import com.google.android.exoplayer2.ui.PlayerView;
    
    import java.lang.ref.WeakReference;
    
    import static android.content.Context.MODE_PRIVATE;
    
    public class MainActivity extends AppCompatActivity {
    
        private static final String TAG = "MyApp";
    
        private ActivityMainBinding binding;
        private SimpleExoPlayer mPlayer;
        private PlayerView playerView;
        private MediaButtonReceiver mediaButtonReceiver;
        private ServiceConnection serviceConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                MediaButtonReceiver receiver = ((MediaButtonReceiver.LocalBinder) service).getService();
                mediaButtonReceiver = receiver;
                receiver.registerReceiver(mediaButtonReceiver, new IntentFilter(ACTION_MEDIA_BUTTON));
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
                mediaButtonReceiver.unregisterReceiver(mediaButtonReceiver);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            binding = ActivityMainBinding.inflate(getLayoutInflater());
            setContentView(binding.getRoot());
    
            initPlayer();
    
            startService(new Intent(this, MyService.class));
    
            // 注册MediaButtonReceiver
            mediaButtonReceiver = new MediaButtonReceiver();
            IntentFilter filter = new IntentFilter();
            filter.addAction(ACTION_MEDIA_BUTTON);
            registerReceiver(mediaButtonReceiver, filter);
    
            // 初始化其他组件
            initPlayerView();
        }
    
        private void initPlayer() {
            mPlayer = ExoPlayerFactory.newSimpleInstance(this);
            playerView = findViewById(R.id.player_view);
            playerView.setPlayer(mPlayer);
        }
    
        private void initPlayerView() {
            playerView.setVisibility(View.VISIBLE);
        }
    
        @Override
        protected void onDestroy() {
            unregisterReceiver(mediaButtonReceiver);
            stopService(new Intent(this, MyService.class));
            super.onDestroy();
        }
    
        private void startService(Intent intent) {
            startService(intent);
        }
    
        private void stopService(Intent intent) {
            stopService(intent);
        }
    
        private void playVideo(String videoId) {
            // 播放视频到playerView
            mPlayer.prepareAsync(videoId);
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            // 在暂停状态下调用
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            // 在恢复状态调用
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            // 在停止状态调用
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            // 在开始状态调用
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
            // 在重启状态调用
        }
    
        @Override
        protected void onLowMemory() {
            super.onLowMemory();
            // 在低内存状态调用
        }
    }
    

    步骤4: 实现MediaButtonListener

    最后,为MediaButtonReceiver中的handleMediaButtonEvent方法编写具体的逻辑来处理MediaButton事件。

    private void handleMediaButtonEvent(Intent intent) {
        String action = intent.getAction();
        if (ACTION_MEDIA_BUTTON.equals(action)) {
            String mediaButtonCommand = intent.getStringExtra(MediaButtonReceiver.EXTRA_COMMAND);
            switch (mediaButtonCommand) {
                case "accept":
                    acceptCall();
                    break;
                case "decline":
                    declineCall();
                    break;
                default:
                    System.out.println("Unknown command: " + mediaButtonCommand);
            }
        } else {
            System.out.println("Unknown action: " + action);
        }
    }
    
    private void acceptCall() {
        // 处理接受呼叫逻辑
    }
    
    private void declineCall() {
        // 处理拒绝呼叫逻辑
    }
    

    步骤5: 使用Bluetooth键控

    为了在来电时使用MediaButton控制接听,您可以利用Android的蓝牙API来触发广播。当用户按下蓝牙键控时,系统会向所有连接的设备发送一个特定的广播。

    Intent bluetoothKeyIntent = new Intent(Bluetooth.KEY_EVENT);
    bluetoothKeyIntent.putExtra(Bluetooth.EXTRA_KEYCODE, KeyEvent.KEYCODE_MEDIA_BUTTON);
    sendBroadcast(bluetoothKeyIntent);
    

    结论

    综上所述,虽然使用MediaButton Receiver和蓝牙键控方案在理论上可行,但由于涉及权限问题以及蓝牙模块本身的限制,实际操作起来可能会遇到不少挑战。因此,建议还是采用更安全、可控的方式,例如使用蓝牙遥控器或其他技术手段,而不是直接依赖MediaButton。

    评论

报告相同问题?