app 在前台的监听方式:
@Override
boolean onKeyDown(int keyCode, KeyEvent event) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return super.onKeyDown(keyCode, event);
}
switch (keyCode) {
case KeyEvent.KEYCODE_MEDIA_PLAY:
//这个地方写处理事件
return true;
}
return super.onKeyDown(keyCode, event);
}
app 后台+前台 同时监听:
AndroidManifest.xml 文件:
1、添加 receiver
2、添加 service
<application>
<receiver
android:name=".MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<service
android:name=".BackgroundMusicService"
android:exported="true"
android:enabled="true"
>
<intent-filter >
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</service>
</application>
MediaButtonReceiver.java 文件:
public class MediaButtonReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "receiver", Toast.LENGTH_SHORT).show();//应用是最后一个播放过音频的,则会被通知
System.out.println("receive");
}
}
BackgroundMusicService.java 文件:
注意:必须创建通知,否则应用会在五秒后报错闪退
public class BackgroundMusicService extends Service {
// MediaPlayer player;
Notification customNotification;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
// player = MediaPlayer.create(this, R.raw.numb); // 注意,应用需要在启动时候播放一段音频来获取按钮事件通知的优先权
// player.setLooping(false);
// player.setVolume(100, 100);
setNotification();
startForeground(200, customNotification);
}
private static final String CHANNEL_ID = "channelID";
private void setNotification() {
RemoteViews rv = new RemoteViews(getPackageName(), R.layout.custom_notification);//通知布局样式
customNotification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.more)
.setCustomContentView(rv)
.build();
NotificationChannel channel = null;
NotificationManager notificationManager = (NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
channel = new NotificationChannel(CHANNEL_ID, "channel_name", NotificationManager.IMPORTANCE_DEFAULT);
notificationManager.createNotificationChannel(channel);
}
}
public void stop(){
// player.pause();
}
public void play(){
// player.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "onStartCommand", Toast.LENGTH_SHORT).show();
return Service.START_STICKY;
}
@Override
public void onDestroy() {
// player.stop();
// player.release();
}
}
MainActivity.java 文件:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
media();
}
// 这个地方需要注意ms必须为成员变量,不能是局部变量,否则在应用进入后台状态会被垃圾回收器回收掉
MediaSessionCompat ms;
PlaybackStateCompat ps;
private void media(){
Intent svc = new Intent(this, BackgroundMusicService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startService(svc);
}
ms = new MediaSessionCompat(this, "My__MediaSessionTag");
ms.setActive(true);
ms.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
mediaButtonIntent.setClass(this, MediaButtonReceiver.class);
ms.setMediaButtonReceiver(PendingIntent.getBroadcast(this, 100, mediaButtonIntent, 0));
ps = new PlaybackStateCompat.Builder().setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE
| PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE |
PlaybackStateCompat.ACTION_SKIP_TO_NEXT | PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
PlaybackStateCompat.ACTION_FAST_FORWARD | PlaybackStateCompat.ACTION_REWIND)
.setState(PlaybackStateCompat.STATE_PAUSED, 0 /*PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN*/, 1f)
.build();
ms.setPlaybackState(ps);
ms.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS);
//应用在前台、后台(活动状态)会触发这里的事件
ms.setCallback(new MediaSessionCompat.Callback() {
@Override
public void onCommand(@NonNull String command, @Nullable Bundle args, @Nullable ResultReceiver cb) {
super.onCommand(command, args, cb);
System.out.println("onCommand");
}
@Override
public void onPlay() {
super.onPlay();
System.out.println("onPlay");
}
@Override
public void onPause() {
super.onPause();
System.out.println("onPause");
}
@Override
public void onStop() {
super.onStop();
System.out.println("onStop");
}
});
}
最后附图 耳机键按下后的流程图:
分类:
frontend / android
, frontend
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库