修复Android 13的闪退问题

This commit is contained in:
muqing 2023-12-27 12:13:53 +08:00
parent b28e67237f
commit a6672148c6
6 changed files with 142 additions and 36 deletions

View File

@ -66,7 +66,11 @@
<service <service
android:name=".bfqkz" android:name=".bfqkz"
android:exported="false" /> android:exported="false">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
<service android:name=".mq.floating" /> <service android:name=".mq.floating" />
<receiver <receiver
android:name=".MyButtonClickReceiver" android:name=".MyButtonClickReceiver"

View File

@ -113,12 +113,14 @@ public class MediaPlayer extends android.media.MediaPlayer {
reset(); reset();
super.setDataSource(path); super.setDataSource(path);
prepare(); prepare();
setTX();
} }
public void setTX() { public void setTX() {
Glide.with(main.application) Glide.with(main.application)
.asBitmap() .asBitmap()
.load(bfqkz.xm.picurl) .load(bfqkz.xm.picurl)
.error(R.drawable.icon)
.listener(new RequestListener<Bitmap>() { .listener(new RequestListener<Bitmap>() {
@Override @Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, public boolean onLoadFailed(@Nullable GlideException e, Object model,

View File

@ -1,17 +1,22 @@
package com.muqingbfq; package com.muqingbfq;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Service; import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat; import android.support.v4.media.session.PlaybackStateCompat;
import android.text.TextUtils; import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media.MediaBrowserServiceCompat;
import com.muqingbfq.api.url; import com.muqingbfq.api.url;
import com.muqingbfq.mq.BluetoothMusicController; import com.muqingbfq.mq.BluetoothMusicController;
@ -22,7 +27,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
public class bfqkz extends Service { public class bfqkz extends MediaBrowserServiceCompat {
public static MediaPlayer mt = new MediaPlayer(); public static MediaPlayer mt = new MediaPlayer();
public static List<MP3> list = new ArrayList<>(); public static List<MP3> list = new ArrayList<>();
public static List<MP3> lishi_list = new ArrayList<>(); public static List<MP3> lishi_list = new ArrayList<>();
@ -32,6 +37,7 @@ public class bfqkz extends Service {
public static boolean like_bool; public static boolean like_bool;
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
public static com.muqingbfq.mq.NotificationManagerCompat notify; public static com.muqingbfq.mq.NotificationManagerCompat notify;
public static int getmti(int s) { public static int getmti(int s) {
int i = bfqkz.list.indexOf(xm); int i = bfqkz.list.indexOf(xm);
if (s == 1) { if (s == 1) {
@ -77,10 +83,12 @@ public class bfqkz extends Service {
public static class mp3 extends Thread { public static class mp3 extends Thread {
String id; String id;
public mp3(String id) { public mp3(String id) {
this.id = id; this.id = id;
start(); start();
} }
@Override @Override
public void run() { public void run() {
super.run(); super.run();
@ -90,7 +98,6 @@ public class bfqkz extends Service {
public static MediaSessionCompat mSession; public static MediaSessionCompat mSession;
public static MediaMetadataCompat build;
public static PlaybackStateCompat playback; public static PlaybackStateCompat playback;
@Override @Override
@ -98,15 +105,24 @@ public class bfqkz extends Service {
super.onCreate(); super.onCreate();
com.muqingbfq.api.playlist.hq_hc(bfqkz.lishi_list); com.muqingbfq.api.playlist.hq_hc(bfqkz.lishi_list);
new BluetoothMusicController(this); new BluetoothMusicController(this);
mSession = new MediaSessionCompat(this, "MusicService");
playback = new PlaybackStateCompat.Builder() playback = new PlaybackStateCompat.Builder()
.setState(PlaybackStateCompat.STATE_NONE, 0, 1.0f) .setState(PlaybackStateCompat.STATE_NONE, 0, 1.0f)
.build(); .build();
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setComponent(new ComponentName(this, home.class));//用ComponentName得到class对象
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);// 关键的一步设置启动模式两种情况
PendingIntent pendingIntent = com.muqingbfq.mq.NotificationManagerCompat.getActivity(this, intent);
mSession = new MediaSessionCompat(this, "MusicService",
home.componentName, pendingIntent);
mSession.setCallback(new callback()); mSession.setCallback(new callback());
mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
mSession.setPlaybackState(playback); mSession.setPlaybackState(playback);
mSession.setMetadata(build); // mSession.setActive(true);
mSession.setActive(true); setSessionToken(mSession.getSessionToken());
notify = new com.muqingbfq.mq.NotificationManagerCompat(this); notify = new com.muqingbfq.mq.NotificationManagerCompat(this);
} }
@ -172,6 +188,17 @@ public class bfqkz extends Service {
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
return null; return null;
} }
@Nullable
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
return null;
}
@Override
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
}
/* /*
public class MyBinder extends Binder { public class MyBinder extends Binder {
@ -184,7 +211,7 @@ public class bfqkz extends Service {
public static void updateNotification() { public static void updateNotification() {
try { try {
// 更新通知栏的播放状态 // 更新通知栏的播放状态
if (notify.notificationBuilder != null) { if (bfqkz.notify != null && notify.notificationBuilder != null) {
notify.tzl(); notify.tzl();
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -61,7 +61,12 @@ public class wode extends Fragment {
new user_message(); new user_message();
// int k = (int) (main.k / getResources().getDisplayMetrics().density + 0.5f); // int k = (int) (main.k / getResources().getDisplayMetrics().density + 0.5f);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 4); GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 4){
@Override
public boolean canScrollVertically() {
return false;//禁止滑动
}
};
binding.recyclerview1.setLayoutManager(gridLayoutManager); binding.recyclerview1.setLayoutManager(gridLayoutManager);
final Object[][] lista = { final Object[][] lista = {
{R.drawable.bf, "最近播放", "mp3_hc.json"}, {R.drawable.bf, "最近播放", "mp3_hc.json"},
@ -73,6 +78,7 @@ public class wode extends Fragment {
{R.drawable.paihangbang, "排行榜", "排行榜"}, {R.drawable.paihangbang, "排行榜", "排行榜"},
{R.drawable.icon, "开发中", ""} {R.drawable.icon, "开发中", ""}
}; };
binding.recyclerview1.setFocusable(false);
binding.recyclerview1.setAdapter(new RecyclerView.Adapter<VH>() { binding.recyclerview1.setAdapter(new RecyclerView.Adapter<VH>() {
@NonNull @NonNull
@Override @Override

View File

@ -1,10 +1,12 @@
package com.muqingbfq; package com.muqingbfq;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.media.MediaBrowserCompat;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@ -31,6 +33,8 @@ public class home extends AppCompatActivity {
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
public static AppCompatActivity appCompatActivity; public static AppCompatActivity appCompatActivity;
ActivityHomeBinding binding; ActivityHomeBinding binding;
public MediaBrowserCompat mBrowser;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
appCompatActivity = this; appCompatActivity = this;
@ -54,12 +58,16 @@ public class home extends AppCompatActivity {
com.muqingbfq.fragment.sz.switch_sz(home.this, item.getItemId()); com.muqingbfq.fragment.sz.switch_sz(home.this, item.getItemId());
return false; return false;
}); });
//初始化播放器组件 //初始化播放器组件
// 启动Service // 启动Service
if (serviceIntent == null) { componentName = new ComponentName(this, bfqkz.class);
serviceIntent = new Intent(this, bfqkz.class); mBrowser = new MediaBrowserCompat(
startService(serviceIntent); this,componentName
} ,//绑定服务端
browserConnectionCallback,//设置连接回调
null
);
//检测更新 //检测更新
new gj.jianchagengxin(this); new gj.jianchagengxin(this);
binding.editView.setOnClickListener(view -> binding.editView.setOnClickListener(view ->
@ -70,14 +78,28 @@ public class home extends AppCompatActivity {
} }
} }
List<Fragment> list = new ArrayList<>(); public static ComponentName componentName;
@Override
protected void onStart() {
super.onStart();
//Browser发送连接请求
mBrowser.connect();
}
@Override
protected void onStop() {
super.onStop();
mBrowser.disconnect();
}
private final List<Fragment> list = new ArrayList<>();
private class adaper extends FragmentStateAdapter { private class adaper extends FragmentStateAdapter {
public adaper(@NonNull FragmentActivity fragmentActivity) { public adaper(@NonNull FragmentActivity fragmentActivity) {
super(fragmentActivity); super(fragmentActivity);
list.add(new gd_adapter()); list.add(new gd_adapter());
list.add(new wode()); list.add(new wode());
} }
@NonNull @NonNull
@Override @Override
public Fragment createFragment(int position) { public Fragment createFragment(int position) {
@ -91,7 +113,6 @@ public class home extends AppCompatActivity {
public void UI() { public void UI() {
binding.viewPager.setAdapter(new adaper(this)); binding.viewPager.setAdapter(new adaper(this));
// ViewPager2 绑定到 TabLayout // ViewPager2 绑定到 TabLayout
binding.tablayout.setOnItemSelectedListener(item -> { binding.tablayout.setOnItemSelectedListener(item -> {
int itemId = item.getItemId(); int itemId = item.getItemId();
@ -129,8 +150,6 @@ public class home extends AppCompatActivity {
} }
}); });
} }
private static Intent serviceIntent;
@Override @Override
protected void onPause() { protected void onPause() {
super.onPause(); super.onPause();
@ -182,4 +201,55 @@ public class home extends AppCompatActivity {
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
/**
* 连接状态的回调接口连接成功时会调用onConnected()方法
*/
private MediaBrowserCompat.ConnectionCallback browserConnectionCallback=
new MediaBrowserCompat.ConnectionCallback(){
@Override
public void onConnected() {
//必须在确保连接成功的前提下执行订阅的操作
if (mBrowser.isConnected()) {
//mediaId即为MediaBrowserService.onGetRoot的返回值
//若Service允许客户端连接则返回结果不为null其值为数据内容层次结构的根ID
//若拒绝连接则返回null
String mediaId = mBrowser.getRoot();
//Browser通过订阅的方式向Service请求数据发起订阅请求需要两个参数其一为mediaId
//而如果该mediaId已经被其他Browser实例订阅则需要在订阅之前取消mediaId的订阅者
//虽然订阅一个 已被订阅的mediaId 时会取代原Browser的订阅回调但却无法触发onChildrenLoaded回调
//ps虽然基本的概念是这样的但是Google在官方demo中有这么一段注释...
// This is temporary: A bug is being fixed that will make subscribe
// consistently call onChildrenLoaded initially, no matter if it is replacing an existing
// subscriber or not. Currently this only happens if the mediaID has no previous
// subscriber or if the media content changes on the service side, so we need to
// unsubscribe first.
//大概的意思就是现在这里还有BUG即只要发送订阅请求就会触发onChildrenLoaded回调
//所以无论怎样我们发起订阅请求之前都需要先取消订阅
mBrowser.unsubscribe(mediaId);
//之前说到订阅的方法还需要一个参数即设置订阅回调SubscriptionCallback
//当Service获取数据后会将数据发送回来此时会触发SubscriptionCallback.onChildrenLoaded回调
mBrowser.subscribe(mediaId, browserSubscriptionCallback);
}
}
@Override
public void onConnectionFailed() {
gj.sc("连接失败!");
}
};
/**
* 向媒体服务器(MediaBrowserService)发起数据订阅请求的回调接口
*/
private final MediaBrowserCompat.SubscriptionCallback browserSubscriptionCallback =
new MediaBrowserCompat.SubscriptionCallback(){
@Override
public void onChildrenLoaded(@NonNull String parentId,
@NonNull List<MediaBrowserCompat.MediaItem> children) {
}
};
} }

View File

@ -62,15 +62,9 @@ public class NotificationManagerCompat {
setAction("syq")); setAction("syq"));
pendingIntent_xyq = getBroadcast(context, my. pendingIntent_xyq = getBroadcast(context, my.
setAction("xyq")); setAction("xyq"));
// 取消操作的PendingIntent
// 取消操作的PendingIntent
/* PendingIntent cancelIntent = MediaButtonReceiver.buildMediaButtonPendingIntent(context,
PlaybackStateCompat.ACTION_STOP);*/
style = new androidx.media.app.NotificationCompat.MediaStyle() style = new androidx.media.app.NotificationCompat.MediaStyle()
.setShowActionsInCompactView(0, 1, 2) .setShowActionsInCompactView(0, 1, 2)
.setMediaSession(bfqkz.mSession.getSessionToken()); .setMediaSession(bfqkz.mSession.getSessionToken());
// .setShowCancelButton(true)
// .setCancelButtonIntent(cancelIntent);
notificationManager = androidx.core.app.NotificationManagerCompat.from(context); notificationManager = androidx.core.app.NotificationManagerCompat.from(context);
notificationBuilder = getNotificationBuilder(context) notificationBuilder = getNotificationBuilder(context)
.setSmallIcon(R.drawable.icon) .setSmallIcon(R.drawable.icon)
@ -96,11 +90,6 @@ public class NotificationManagerCompat {
name = bfqkz.xm.name; name = bfqkz.xm.name;
zz = bfqkz.xm.zz; zz = bfqkz.xm.zz;
} }
bfqkz.build = new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, name)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, zz)
.build();
bfqkz.mSession.setMetadata(bfqkz.build);
notificationBuilder.mActions.clear(); notificationBuilder.mActions.clear();
notificationBuilder.addAction(android.R.drawable.ic_media_previous, "syq", pendingIntent_syq) // #0 notificationBuilder.addAction(android.R.drawable.ic_media_previous, "syq", pendingIntent_syq) // #0
.addAction(bfqkz.mt.isPlaying() ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play .addAction(bfqkz.mt.isPlaying() ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play
@ -111,6 +100,7 @@ public class NotificationManagerCompat {
.setOngoing(bfqkz.mt.isPlaying()); .setOngoing(bfqkz.mt.isPlaying());
notificationManager_notify(); notificationManager_notify();
} }
private PendingIntent pendingIntent_kg, private PendingIntent pendingIntent_kg,
pendingIntent_syq, pendingIntent_syq,
pendingIntent_xyq; pendingIntent_xyq;
@ -123,17 +113,22 @@ public class NotificationManagerCompat {
notificationManager.notify(1, notificationBuilder.build()); notificationManager.notify(1, notificationBuilder.build());
} }
@SuppressLint({"MissingPermission", "RestrictedApi", "NotifyDataSetChanged"})
public void setBitmap() { public void setBitmap() {
if (bfq.bitmap == null) { Media.setImageBitmap();
bfq.bitmap = BitmapFactory.decodeResource(context.getResources(),
R.drawable.icon);
}
if (notificationManager != null) { if (notificationManager != null) {
if (ActivityCompat.checkSelfPermission(home.appCompatActivity, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
notificationBuilder.setLargeIcon(bfq.bitmap); notificationBuilder.setLargeIcon(bfq.bitmap);
notificationManager.notify(1, notificationBuilder.build()); notificationManager.notify(1, notificationBuilder.build());
} }
Media.setImageBitmap();
} }
private NotificationCompat.Builder getNotificationBuilder(Context context) { private NotificationCompat.Builder getNotificationBuilder(Context context) {
@ -152,7 +147,9 @@ public class NotificationManagerCompat {
return PendingIntent.getBroadcast(context, 0, intent, flag); return PendingIntent.getBroadcast(context, 0, intent, flag);
} }
private PendingIntent getActivity(Context context, Intent intent) {
public static PendingIntent getActivity(Context context, Intent intent) {
int flag; int flag;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flag = PendingIntent.FLAG_IMMUTABLE; flag = PendingIntent.FLAG_IMMUTABLE;