From a6672148c6bf7a386b724cfcc1352afd190a4e2f Mon Sep 17 00:00:00 2001 From: MUQING <1966944300@qq.com> Date: Wed, 27 Dec 2023 12:13:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DAndroid=2013=E7=9A=84?= =?UTF-8?q?=E9=97=AA=E9=80=80=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 6 +- .../main/java/com/muqingbfq/MediaPlayer.java | 2 + app/src/main/java/com/muqingbfq/bfqkz.java | 41 +++++++-- .../java/com/muqingbfq/fragment/wode.java | 8 +- app/src/main/java/com/muqingbfq/home.java | 88 +++++++++++++++++-- .../mq/NotificationManagerCompat.java | 33 ++++--- 6 files changed, 142 insertions(+), 36 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cf7f148..a6e5cc9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -66,7 +66,11 @@ + android:exported="false"> + + + + () { @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, diff --git a/app/src/main/java/com/muqingbfq/bfqkz.java b/app/src/main/java/com/muqingbfq/bfqkz.java index 94f0b16..08fb333 100644 --- a/app/src/main/java/com/muqingbfq/bfqkz.java +++ b/app/src/main/java/com/muqingbfq/bfqkz.java @@ -1,17 +1,22 @@ package com.muqingbfq; import android.annotation.SuppressLint; -import android.app.Service; +import android.app.PendingIntent; +import android.content.ComponentName; import android.content.Intent; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.IBinder; +import android.support.v4.media.MediaBrowserCompat; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; import android.text.TextUtils; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.media.MediaBrowserServiceCompat; import com.muqingbfq.api.url; import com.muqingbfq.mq.BluetoothMusicController; @@ -22,7 +27,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public class bfqkz extends Service { +public class bfqkz extends MediaBrowserServiceCompat { public static MediaPlayer mt = new MediaPlayer(); public static List list = new ArrayList<>(); public static List lishi_list = new ArrayList<>(); @@ -32,6 +37,7 @@ public class bfqkz extends Service { public static boolean like_bool; @SuppressLint("StaticFieldLeak") public static com.muqingbfq.mq.NotificationManagerCompat notify; + public static int getmti(int s) { int i = bfqkz.list.indexOf(xm); if (s == 1) { @@ -77,10 +83,12 @@ public class bfqkz extends Service { public static class mp3 extends Thread { String id; + public mp3(String id) { this.id = id; start(); } + @Override public void run() { super.run(); @@ -90,7 +98,6 @@ public class bfqkz extends Service { public static MediaSessionCompat mSession; - public static MediaMetadataCompat build; public static PlaybackStateCompat playback; @Override @@ -98,15 +105,24 @@ public class bfqkz extends Service { super.onCreate(); com.muqingbfq.api.playlist.hq_hc(bfqkz.lishi_list); new BluetoothMusicController(this); - mSession = new MediaSessionCompat(this, "MusicService"); playback = new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_NONE, 0, 1.0f) .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.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setPlaybackState(playback); - mSession.setMetadata(build); - mSession.setActive(true); +// mSession.setActive(true); + setSessionToken(mSession.getSessionToken()); + notify = new com.muqingbfq.mq.NotificationManagerCompat(this); } @@ -172,6 +188,17 @@ public class bfqkz extends Service { public IBinder onBind(Intent intent) { 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> result) { + + } /* public class MyBinder extends Binder { @@ -184,7 +211,7 @@ public class bfqkz extends Service { public static void updateNotification() { try { // 更新通知栏的播放状态 - if (notify.notificationBuilder != null) { + if (bfqkz.notify != null && notify.notificationBuilder != null) { notify.tzl(); } } catch (Exception e) { diff --git a/app/src/main/java/com/muqingbfq/fragment/wode.java b/app/src/main/java/com/muqingbfq/fragment/wode.java index 9c3635f..388d04d 100644 --- a/app/src/main/java/com/muqingbfq/fragment/wode.java +++ b/app/src/main/java/com/muqingbfq/fragment/wode.java @@ -61,7 +61,12 @@ public class wode extends Fragment { new user_message(); // 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); final Object[][] lista = { {R.drawable.bf, "最近播放", "mp3_hc.json"}, @@ -73,6 +78,7 @@ public class wode extends Fragment { {R.drawable.paihangbang, "排行榜", "排行榜"}, {R.drawable.icon, "开发中", ""} }; + binding.recyclerview1.setFocusable(false); binding.recyclerview1.setAdapter(new RecyclerView.Adapter() { @NonNull @Override diff --git a/app/src/main/java/com/muqingbfq/home.java b/app/src/main/java/com/muqingbfq/home.java index 80fb3ee..835e6cc 100644 --- a/app/src/main/java/com/muqingbfq/home.java +++ b/app/src/main/java/com/muqingbfq/home.java @@ -1,10 +1,12 @@ package com.muqingbfq; import android.annotation.SuppressLint; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; +import android.support.v4.media.MediaBrowserCompat; import android.util.DisplayMetrics; import android.view.Menu; import android.view.MenuItem; @@ -31,6 +33,8 @@ public class home extends AppCompatActivity { @SuppressLint("StaticFieldLeak") public static AppCompatActivity appCompatActivity; ActivityHomeBinding binding; + + public MediaBrowserCompat mBrowser; @Override protected void onCreate(Bundle savedInstanceState) { appCompatActivity = this; @@ -54,12 +58,16 @@ public class home extends AppCompatActivity { com.muqingbfq.fragment.sz.switch_sz(home.this, item.getItemId()); return false; }); + //初始化播放器组件 // 启动Service - if (serviceIntent == null) { - serviceIntent = new Intent(this, bfqkz.class); - startService(serviceIntent); - } + componentName = new ComponentName(this, bfqkz.class); + mBrowser = new MediaBrowserCompat( + this,componentName + ,//绑定服务端 + browserConnectionCallback,//设置连接回调 + null + ); //检测更新 new gj.jianchagengxin(this); binding.editView.setOnClickListener(view -> @@ -70,14 +78,28 @@ public class home extends AppCompatActivity { } } - List 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 list = new ArrayList<>(); private class adaper extends FragmentStateAdapter { public adaper(@NonNull FragmentActivity fragmentActivity) { super(fragmentActivity); list.add(new gd_adapter()); list.add(new wode()); } - @NonNull @Override public Fragment createFragment(int position) { @@ -91,7 +113,6 @@ public class home extends AppCompatActivity { public void UI() { binding.viewPager.setAdapter(new adaper(this)); - // 将 ViewPager2 绑定到 TabLayout binding.tablayout.setOnItemSelectedListener(item -> { int itemId = item.getItemId(); @@ -129,8 +150,6 @@ public class home extends AppCompatActivity { } }); } - - private static Intent serviceIntent; @Override protected void onPause() { super.onPause(); @@ -182,4 +201,55 @@ public class home extends AppCompatActivity { } 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 children) { + } + }; } \ No newline at end of file diff --git a/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java b/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java index 628252e..1580560 100644 --- a/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java +++ b/app/src/main/java/com/muqingbfq/mq/NotificationManagerCompat.java @@ -62,15 +62,9 @@ public class NotificationManagerCompat { setAction("syq")); pendingIntent_xyq = getBroadcast(context, my. setAction("xyq")); - // 取消操作的PendingIntent -// 取消操作的PendingIntent -/* PendingIntent cancelIntent = MediaButtonReceiver.buildMediaButtonPendingIntent(context, - PlaybackStateCompat.ACTION_STOP);*/ style = new androidx.media.app.NotificationCompat.MediaStyle() .setShowActionsInCompactView(0, 1, 2) .setMediaSession(bfqkz.mSession.getSessionToken()); -// .setShowCancelButton(true) -// .setCancelButtonIntent(cancelIntent); notificationManager = androidx.core.app.NotificationManagerCompat.from(context); notificationBuilder = getNotificationBuilder(context) .setSmallIcon(R.drawable.icon) @@ -96,11 +90,6 @@ public class NotificationManagerCompat { name = bfqkz.xm.name; 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.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 @@ -111,6 +100,7 @@ public class NotificationManagerCompat { .setOngoing(bfqkz.mt.isPlaying()); notificationManager_notify(); } + private PendingIntent pendingIntent_kg, pendingIntent_syq, pendingIntent_xyq; @@ -123,17 +113,22 @@ public class NotificationManagerCompat { notificationManager.notify(1, notificationBuilder.build()); } - @SuppressLint({"MissingPermission", "RestrictedApi", "NotifyDataSetChanged"}) public void setBitmap() { - if (bfq.bitmap == null) { - bfq.bitmap = BitmapFactory.decodeResource(context.getResources(), - R.drawable.icon); - } + Media.setImageBitmap(); 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); notificationManager.notify(1, notificationBuilder.build()); } - Media.setImageBitmap(); } private NotificationCompat.Builder getNotificationBuilder(Context context) { @@ -152,7 +147,9 @@ public class NotificationManagerCompat { return PendingIntent.getBroadcast(context, 0, intent, flag); } - private PendingIntent getActivity(Context context, Intent intent) { + + + public static PendingIntent getActivity(Context context, Intent intent) { int flag; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { flag = PendingIntent.FLAG_IMMUTABLE;