diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0ed1383..96d7327 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -23,11 +23,14 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Clean project + run: ./gradlew clean + - name: Build APK run: ./gradlew assembleDebug - name: Upload APK as artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: app-debug path: app/build/outputs/apk/debug/app-debug.apk \ No newline at end of file diff --git a/README.md b/README.md index c7106fd..150e8d6 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ -# zz-android-old -> use API 33 to build and api 28 to test, estimated time to finish: 6 weeks - 7 months, hehe +# ZryteZene Java Mobile +> Currently under development by 1 person, so it may take longer to finish, its hard to implement the run-in-background system where since Android 14 or newer restricted the background services the most. Estimated time to finish: 6 weeks - 7 months, hehe. + +# Overview +**ZryteZene** is a multi-platform app to allow users to stream musics across various devices seamlessly, such as Android, desktop and web platform. Its completely free and ad-free too. + +# Requirements +- Minimum SDK : 27 (Oreo) +- Compile SDK : 34 (Upside Down Cake) +- Language : Java - Native \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 18cb271..97437f1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,12 +5,12 @@ plugins { android { namespace = "tw.music.streamer" - compileSdk = 33 + compileSdk = 34 defaultConfig { applicationId = "tw.music.streamer" minSdk = 27 - targetSdk = 33 + targetSdk = 34 versionCode = 1 versionName = "1.0" @@ -36,10 +36,16 @@ android { } } +repositories { + google() + mavenCentral() +} + dependencies { implementation("androidx.lifecycle:lifecycle-livedata:2.5.1") implementation("androidx.constraintlayout:constraintlayout:2.1.4") implementation("com.google.android.material:material:1.9.0") + implementation("androidx.media:media:1.7.0") implementation("androidx.navigation:navigation-ui:2.5.3") implementation("androidx.lifecycle:lifecycle-viewmodel:2.5.1") implementation("androidx.appcompat:appcompat:1.6.1") @@ -52,6 +58,8 @@ dependencies { implementation("com.google.firebase:firebase-storage:20.3.0") implementation("com.google.android.gms:play-services-tasks:18.0.2") implementation("com.squareup.okhttp3:okhttp:4.11.0") + implementation("com.android.support:support-media-compat:28.0.0") + } apply(plugin = "com.google.gms.google-services") \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d5b10ba..3606cc3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,9 +6,9 @@ - - + + - + \ No newline at end of file diff --git a/app/src/main/java/tw/music/streamer/MainActivity.java b/app/src/main/java/tw/music/streamer/MainActivity.java index face5fc..fc5b7d1 100644 --- a/app/src/main/java/tw/music/streamer/MainActivity.java +++ b/app/src/main/java/tw/music/streamer/MainActivity.java @@ -54,7 +54,6 @@ public class MainActivity extends AppCompatActivity { private Timer _timer = new Timer(); - //private FirebaseDatabase _firebase = FirebaseDatabase.getInstance(); private HashMap map = new HashMap<>(); private boolean isBanned = false; @@ -92,25 +91,25 @@ public class MainActivity extends AppCompatActivity { private TextView textview4; private SharedPreferences data; - private DatabaseReference update_db;// = FirebaseDatabase.getInstance().getReference("update/version"); + private DatabaseReference update_db; private ChildEventListener _update_db_child_listener; private Intent intent = new Intent(); private AlertDialog.Builder d; - private DatabaseReference profile;// = FirebaseDatabase.getInstance().getReference("profile/text"); + private DatabaseReference profile; private ChildEventListener _profile_child_listener; private FirebaseAuth Auth; private OnCompleteListener _Auth_create_user_listener; private OnCompleteListener _Auth_sign_in_listener; private OnCompleteListener _Auth_reset_password_listener; private Intent activityChanger = new Intent(); - private DatabaseReference prof_img;// = FirebaseDatabase.getInstance().getReference("profile/image"); + private DatabaseReference prof_img; private ChildEventListener _prof_img_child_listener; private TimerTask timer; private ObjectAnimator objectanim3 = new ObjectAnimator(); private RequestNetwork internetchecker; private RequestNetwork.RequestListener _internetchecker_request_listener; private TimerTask delaynointernet; - private DatabaseReference prof_bans;// = FirebaseDatabase.getInstance().getReference("profile/bans"); + private DatabaseReference prof_bans; private ChildEventListener _prof_bans_child_listener; private RequestNetwork rn; private RequestNetwork.RequestListener _rn_request_listener; @@ -121,13 +120,14 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle _savedInstanceState) { super.onCreate(_savedInstanceState); setContentView(R.layout.main); - //com.google.firebase.FirebaseApp.initializeApp(this); - //initialize(_savedInstanceState); - //initializeLogic(); + update_db = FirebaseDatabase.getInstance().getReference("update/version"); + profile = FirebaseDatabase.getInstance().getReference("profile/text"); + prof_img = FirebaseDatabase.getInstance().getReference("profile/image"); + prof_bans = FirebaseDatabase.getInstance().getReference("profile/bans"); + initialize(_savedInstanceState); + initializeLogic(); } - /* - private void initialize(Bundle _savedInstanceState) { linear1 = findViewById(R.id.linear1); @@ -1029,8 +1029,6 @@ private void _checkCookie() { } } - */ - private void _shadow(final View _v, final double _n) { _v.setElevation((float) _n); } diff --git a/app/src/main/java/tw/music/streamer/StreamerActivity.java b/app/src/main/java/tw/music/streamer/StreamerActivity.java index 3bf2117..81e1470 100644 --- a/app/src/main/java/tw/music/streamer/StreamerActivity.java +++ b/app/src/main/java/tw/music/streamer/StreamerActivity.java @@ -128,9 +128,6 @@ public class StreamerActivity extends AppCompatActivity { - private FirebaseDatabase _firebase = FirebaseDatabase.getInstance(); - private FirebaseStorage _firebase_storage = FirebaseStorage.getInstance(); - private Toolbar _toolbar; private DrawerLayout _drawer; private HashMap likes_map = new HashMap<>(); @@ -145,6 +142,7 @@ public class StreamerActivity extends AppCompatActivity { private boolean isSearching = false; private boolean hasPic = false; private HashMap img_maps = new HashMap<>(); + private HashMap tempMap; private ArrayList usrname_list = new ArrayList<>(); private ArrayList> upload_list = new ArrayList<>(); @@ -217,7 +215,6 @@ public class StreamerActivity extends AppCompatActivity { private ScrollView _drawer_vscroll1; private LinearLayout _drawer_linear10; private LinearLayout _drawer_linear_usr; - private LinearLayout _drawer_linear5; private LinearLayout _drawer_linear2; private LinearLayout _drawer_linear6; private LinearLayout _drawer_linear_upload; @@ -259,40 +256,40 @@ public class StreamerActivity extends AppCompatActivity { private ObjectAnimator obj2 = new ObjectAnimator(); private ObjectAnimator obj3 = new ObjectAnimator(); private SharedPreferences data; - private DatabaseReference upload_text = _firebase.getReference("upload/text"); + private DatabaseReference upload_text; private ChildEventListener _upload_text_child_listener; - private DatabaseReference profile_admins = _firebase.getReference("profile/admins"); + private DatabaseReference profile_admins; private ChildEventListener _profile_admins_child_listener; - private DatabaseReference comments_db = _firebase.getReference("upload/msg"); + private DatabaseReference comments_db; private ChildEventListener _comments_db_child_listener; private FirebaseAuth Auth; private OnCompleteListener _Auth_create_user_listener; private OnCompleteListener _Auth_sign_in_listener; private OnCompleteListener _Auth_reset_password_listener; - private DatabaseReference profile = _firebase.getReference("profile/text"); + private DatabaseReference profile; private ChildEventListener _profile_child_listener; - private DatabaseReference fb_likes = _firebase.getReference("upload/likes"); + private DatabaseReference fb_likes; private ChildEventListener _fb_likes_child_listener; - private DatabaseReference prof_img = _firebase.getReference("profile/image"); + private DatabaseReference prof_img; private ChildEventListener _prof_img_child_listener; private Intent intent = new Intent(); private AlertDialog.Builder d; private Intent i2 = new Intent(); - private StorageReference check_quota = _firebase_storage.getReference("/"); + private StorageReference check_quota; private OnCompleteListener _check_quota_upload_success_listener; private OnSuccessListener _check_quota_download_success_listener; private OnSuccessListener _check_quota_delete_success_listener; private OnProgressListener _check_quota_upload_progress_listener; private OnProgressListener _check_quota_download_progress_listener; private OnFailureListener _check_quota_failure_listener; - private StorageReference upload_storage = _firebase_storage.getReference("upload/music"); + private StorageReference upload_storage; private OnCompleteListener _upload_storage_upload_success_listener; private OnSuccessListener _upload_storage_download_success_listener; private OnSuccessListener _upload_storage_delete_success_listener; private OnProgressListener _upload_storage_upload_progress_listener; private OnProgressListener _upload_storage_download_progress_listener; private OnFailureListener _upload_storage_failure_listener; - private StorageReference music_image = _firebase_storage.getReference("upload/image"); + private StorageReference music_image; private OnCompleteListener _music_image_upload_success_listener; private OnSuccessListener _music_image_download_success_listener; private OnSuccessListener _music_image_delete_success_listener; @@ -306,12 +303,6 @@ public class StreamerActivity extends AppCompatActivity { private double _t; private ArrayAdapter Listview2Adapter; private GridView listview2; - private Handler dataHandlerReceiverZero; - private Handler dataHandlerReceiverOne; - private Handler dataHandlerReceiverTwo; - private Handler dataHandlerReceiverThree; - private Handler dataHandlerReceiverFour; - private Handler dataHandlerReceiverFive; private com.google.android.material.tabs.TabLayout x_tab; private androidx.viewpager.widget.ViewPager viewPager; private android.graphics.drawable.AnimationDrawable rocketAnimation; @@ -322,26 +313,25 @@ public class StreamerActivity extends AppCompatActivity { protected void onCreate(Bundle _savedInstanceState) { super.onCreate(_savedInstanceState); setContentView(R.layout.streamer); - com.google.firebase.FirebaseApp.initializeApp(this); + initFirebase(); initialize(_savedInstanceState); - if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED - || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED) { - ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1000); - } else { - initializeLogic(); - } + initializeLogic(); } - @Override - public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - if (requestCode == 1000) { - initializeLogic(); - } + private void initFirebase() { + Auth = FirebaseAuth.getInstance(); + upload_text = FirebaseDatabase.getInstance().getReference("upload/text"); + profile_admins = FirebaseDatabase.getInstance().getReference("profile/admins"); + comments_db = FirebaseDatabase.getInstance().getReference("upload/msg"); + profile = FirebaseDatabase.getInstance().getReference("profile/text"); + fb_likes = FirebaseDatabase.getInstance().getReference("upload/likes"); + prof_img = FirebaseDatabase.getInstance().getReference("profile/image"); + check_quota = FirebaseStorage.getInstance().getReference("/"); + upload_storage = FirebaseStorage.getInstance().getReference("upload/music"); + music_image = FirebaseStorage.getInstance().getReference("upload/image"); } private void initialize(Bundle _savedInstanceState) { - _toolbar = findViewById(R.id._toolbar); setSupportActionBar(_toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -410,7 +400,6 @@ public void onClick(View _v) { _drawer_vscroll1 = _nav_view.findViewById(R.id.vscroll1); _drawer_linear10 = _nav_view.findViewById(R.id.linear10); _drawer_linear_usr = _nav_view.findViewById(R.id.linear_usr); - _drawer_linear5 = _nav_view.findViewById(R.id.linear5); _drawer_linear2 = _nav_view.findViewById(R.id.linear2); _drawer_linear6 = _nav_view.findViewById(R.id.linear6); _drawer_linear_upload = _nav_view.findViewById(R.id.linear_upload); @@ -448,7 +437,6 @@ public void onClick(View _v) { _drawer_text_user = _nav_view.findViewById(R.id.text_user); _drawer_text_email = _nav_view.findViewById(R.id.text_email); data = getSharedPreferences("teamdata", Activity.MODE_PRIVATE); - Auth = FirebaseAuth.getInstance(); d = new AlertDialog.Builder(this); zz = new ZryteZeneAdaptor(this); Intent siop = new Intent(getApplicationContext(), ZryteZenePlay.class); @@ -1854,7 +1842,7 @@ public void onItemClick(AdapterView parent, View view, int _pos, long id) { } } } - _firebase_storage.getReferenceFromUrl("https://firebasestorage.googleapis.com/v0/b/teammusic-tw.appspot.com/o/tm-testfile?alt=media&token=ec852b8b-438c-457a-887d-b289968971ec").getFile(new File(FileUtil.getPackageDataDir(getApplicationContext()).concat("/tm-testfile"))).addOnSuccessListener(_check_quota_download_success_listener).addOnFailureListener(_check_quota_failure_listener).addOnProgressListener(_check_quota_download_progress_listener); + FirebaseStorage.getInstance().getReferenceFromUrl("https://firebasestorage.googleapis.com/v0/b/teammusic-tw.appspot.com/o/tm-testfile?alt=media&token=ec852b8b-438c-457a-887d-b289968971ec").getFile(new File(FileUtil.getPackageDataDir(getApplicationContext()).concat("/tm-testfile"))).addOnSuccessListener(_check_quota_download_success_listener).addOnFailureListener(_check_quota_failure_listener).addOnProgressListener(_check_quota_download_progress_listener); IntentFilter filr = new IntentFilter(ZryteZenePlay.ACTION_UPDATE); registerReceiver(listenerReceiver, filr); zz.requestAction("request-media"); @@ -1904,17 +1892,6 @@ public void onReceive(Context context, Intent intent) { } }; - @Override - protected void onActivityResult(int _requestCode, int _resultCode, Intent _data) { - super.onActivityResult(_requestCode, _resultCode, _data); - - switch (_requestCode) { - - default: - break; - } - } - @Override public void onBackPressed() { if (_drawer.isDrawerOpen(GravityCompat.START)) { @@ -1967,7 +1944,8 @@ public void onStart() { image_user.clearColorFilter(); _drawer_image_user.clearColorFilter(); } - /*if (tmservice != null) { + /* + if (tmservice != null) { if (!currentlyPlaying.equals("") && !tmservice._isMpNull()) { if (currentlyMap.get(currentlyChild.indexOf(currentlyPlaying)).containsKey("img")) { image_album.clearColorFilter(); @@ -1978,8 +1956,8 @@ public void onStart() { text_artist.setTextColor(Color.parseColor(theme_map.get(0).get("colorPrimaryCardText").toString())); } } - }*/ - ((BaseAdapter) listview1.getAdapter()).notifyDataSetChanged(); + } + ((BaseAdapter) listview1.getAdapter()).notifyDataSetChanged();*/ } @Override @@ -2000,7 +1978,7 @@ public void onStop() { @Override public void onDestroy() { super.onDestroy(); - _unbindSvc(); + //_unbindSvc(); } private void _shadow(final View _v, final double _n) { @@ -2153,8 +2131,8 @@ private void _loadTheme() { text_zene.setTextColor(Color.parseColor(theme_map.get(0).get("colorBackgroundCardText").toString())); text_playlist.setTextColor(Color.parseColor(theme_map.get(0).get("colorBackgroundCardText").toString())); edittext_search.setTextColor(Color.parseColor(theme_map.get(0).get("colorBackgroundCardText").toString())); - //x_tab.setSelectedTabIndicatorColor(Color.parseColor(theme_map.get(0).get("colorPrimary").toString())); - //x_tab.setTabTextColors(Color.parseColor(theme_map.get(0).get("colorBackgroundText").toString()), Color.parseColor(theme_map.get(0).get("colorBackgroundText").toString())); + x_tab.setSelectedTabIndicatorColor(Color.parseColor(theme_map.get(0).get("colorPrimary").toString())); + x_tab.setTabTextColors(Color.parseColor(theme_map.get(0).get("colorBackgroundText").toString()), Color.parseColor(theme_map.get(0).get("colorBackgroundText").toString())); { ViewGroup _vg = (ViewGroup) x_tab.getChildAt(0); @@ -2626,27 +2604,28 @@ public void onClick(DialogInterface _dialog, int _which) { private void _play(final String _key) { _CoreProgressLoading(true); - final double _position = currentlyChild.indexOf(_key); + final int _pos = (int) currentlyChild.indexOf(_key); + tempMap = currentlyMap.get(_pos); currentlyPlaying = _key; - text_title.setText(currentlyMap.get((int) _position).get("name").toString()); - if (usrname_list.contains(currentlyMap.get((int) _position).get("uid").toString())) { - text_artist.setText(profile_map.get(usrname_list.indexOf(currentlyMap.get((int) _position).get("uid").toString())).get("username").toString()); + text_title.setText(tempMap.get("name").toString()); + if (usrname_list.contains(tempMap.get("uid").toString())) { + text_artist.setText(profile_map.get(usrname_list.indexOf(tempMap.get("uid").toString())).get("username").toString()); } else { - text_artist.setText(currentlyMap.get((int) _position).get("uid").toString()); + text_artist.setText(tempMap.get("uid").toString()); } - if (adminsList.contains(currentlyMap.get((int) _position).get("uid").toString())) { + if (adminsList.contains(tempMap.get("uid").toString())) { text_artist.setTextColor(Color.parseColor(theme_map.get(0).get("colorButton").toString())); } else { text_artist.setTextColor(Color.parseColor(theme_map.get(0).get("colorPrimaryCardText").toString())); } - if (currentlyMap.get((int) _position).containsKey("img")) { + if (tempMap.containsKey("img")) { image_album.clearColorFilter(); - Glide.with(getApplicationContext()).load(currentlyMap.get((int) _position).get("img").toString()).centerCrop().into(image_album); + Glide.with(getApplicationContext()).load(tempMap.get("img").toString()).centerCrop().into(image_album); } else { image_album.setImageResource(R.drawable.ic_album_white); image_album.setColorFilter(Color.parseColor(theme_map.get(0).get("colorButtonText").toString()), PorterDuff.Mode.MULTIPLY); } - zz.requestAction("play", currentlyMap.get((int) _position).get("url").toString()); + zz.play(tempMap.get("url").toString(), tempMap.get("name").toString(), "ZryteZene", tempMap.containsKey("img") ? tempMap.get("img").toString() : "-"); } private void _shape(final double _tl, final double _tr, final double _bl, final double _br, final String _BGcolor, final String _Scolor, final double _Swidth, final View _view) { @@ -3205,9 +3184,9 @@ public void onClick(DialogInterface dia, int _pos_dialog) { d.setPositiveButton("Yes", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface _dialog, int _which) { - _firebase_storage.getReferenceFromUrl(upload_list.get(_position).get("url").toString()).delete().addOnSuccessListener(_upload_storage_delete_success_listener).addOnFailureListener(_upload_storage_failure_listener); + FirebaseStorage.getInstance().getReferenceFromUrl(upload_list.get(_position).get("url").toString()).delete().addOnSuccessListener(_upload_storage_delete_success_listener).addOnFailureListener(_upload_storage_failure_listener); if (upload_list.get(_position).containsKey("img")) { - _firebase_storage.getReferenceFromUrl(upload_list.get(_position).get("img").toString()).delete().addOnSuccessListener(_music_image_delete_success_listener).addOnFailureListener(_music_image_failure_listener); + FirebaseStorage.getInstance().getReferenceFromUrl(upload_list.get(_position).get("img").toString()).delete().addOnSuccessListener(_music_image_delete_success_listener).addOnFailureListener(_music_image_failure_listener); } upload_text.child(childkey.get(_position)).removeValue(); _customSnack("Delete success!", 1); diff --git a/app/src/main/java/tw/music/streamer/adaptor/ZryteZeneAdaptor.java b/app/src/main/java/tw/music/streamer/adaptor/ZryteZeneAdaptor.java index 1ac7412..475cfe2 100644 --- a/app/src/main/java/tw/music/streamer/adaptor/ZryteZeneAdaptor.java +++ b/app/src/main/java/tw/music/streamer/adaptor/ZryteZeneAdaptor.java @@ -102,4 +102,14 @@ public void requestAction(String a, String b) { ctx.sendBroadcast(jof); if (a.equals("play")) sp = b; } + + public void play(String a, String b, String c, String d) { + Intent jof = new Intent(ZryteZenePlay.ACTION_BROADCAST); + jof.putExtra("action", "play"); + jof.putExtra("path", a); + jof.putExtra("title", b); + jof.putExtra("artist", c); + jof.putExtra("cover", d); + ctx.sendBroadcast(jof); + } } \ No newline at end of file diff --git a/app/src/main/java/tw/music/streamer/notification/ZryteZeneNotification.java b/app/src/main/java/tw/music/streamer/notification/ZryteZeneNotification.java index fde6cf1..dc4059e 100644 --- a/app/src/main/java/tw/music/streamer/notification/ZryteZeneNotification.java +++ b/app/src/main/java/tw/music/streamer/notification/ZryteZeneNotification.java @@ -1,5 +1,7 @@ package tw.music.streamer.notification; +import tw.music.streamer.R; + import android.os.Build; import android.app.Notification; import android.app.PendingIntent; @@ -7,6 +9,20 @@ import android.app.NotificationManager; import android.content.Intent; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.app.NotificationCompat; +import androidx.media.app.NotificationCompat.MediaStyle; +//import androidx.media.session.MediaSessionCompat; + +import android.support.v4.media.session.MediaSessionCompat; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.CustomTarget; +import com.bumptech.glide.request.transition.Transition; import tw.music.streamer.service.ZryteZenePlay; import tw.music.streamer.StreamerActivity; @@ -17,8 +33,8 @@ public static Notification setup(Context a) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel ch = new NotificationChannel( ZryteZenePlay.CHANNEL_ID, - "Music Playback", - NotificationManager.IMPORTANCE_HIGH + "ZryteZene Player", + NotificationManager.IMPORTANCE_LOW ); ch.setSound(null, null); ch.enableLights(false); @@ -35,115 +51,83 @@ public static Notification setup(Context a) { Notification notification = new Notification.Builder(a, ZryteZenePlay.CHANNEL_ID) .setContentTitle("ZryteZene") .setContentText("Idle...") - .setSmallIcon(android.R.drawable.ic_media_play) + .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(openAppPendingIntent) .setOnlyAlertOnce(true) .build(); return notification; } - - public static void update(Context a, String b) { - Intent openAppIntent = new Intent(a, StreamerActivity.class); - PendingIntent openAppPendingIntent = PendingIntent.getActivity(a, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - NotificationManager notificationManager = (NotificationManager) a.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager == null) return; - Notification notification; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - notification = new Notification.Builder(a, ZryteZenePlay.CHANNEL_ID) - .setContentTitle("ZryteZene") - .setContentText(b) - .setSmallIcon(android.R.drawable.ic_media_play) - .setContentIntent(openAppPendingIntent) - .setOngoing(true) - .setOnlyAlertOnce(true) - .build(); + + public static void update(Context a, boolean b, MediaSessionCompat c, String d, String e, String f) { + if (f.equals("-")) { + updateWithMedia(a,b,c,d,e,null); } else { - notification = new Notification.Builder(a) - .setContentTitle("ZryteZene") - .setContentText(b) - .setSmallIcon(android.R.drawable.ic_media_pause) - .setContentIntent(openAppPendingIntent) - .setOngoing(true) - .setOnlyAlertOnce(true) - .build(); + Glide.with(a) + .asBitmap() + .load(f) + .into(new CustomTarget() { + @Override + public void onResourceReady(@NonNull Bitmap g, @NonNull Transition h) { + updateWithMedia(a,b,c,d,e,g); + } + @Override + public void onLoadCleared(@Nullable Drawable i) { + } + }); } - notificationManager.notify(ZryteZenePlay.NOTIFICATION_ID, notification); } - public static void update(Context a, boolean b) { - NotificationManager notificationManager = (NotificationManager) a.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager == null) return; - Intent actionIntent; - PendingIntent actionPendingIntent; - String actionTitle; - int actionIcon; - if (b) { - actionIntent = new Intent(a, ZryteZenePlay.class); - actionIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - actionIntent.putExtra("action","pause"); - actionPendingIntent = PendingIntent.getService(a, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - actionTitle = "Pause"; - actionIcon = android.R.drawable.ic_media_pause; - } else { - actionIntent = new Intent(a, ZryteZenePlay.class); - actionIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - actionIntent.putExtra("action","resume"); - actionPendingIntent = PendingIntent.getService(a, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - actionTitle = "Resume"; - actionIcon = android.R.drawable.ic_media_play; + public static void updateWithMedia(Context a, boolean b, MediaSessionCompat c, String d, String e, Bitmap f) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + NotificationChannel channel = new NotificationChannel(ZryteZenePlay.CHANNEL_ID, "ZryteZene Player", NotificationManager.IMPORTANCE_LOW); + NotificationManager manager = a.getSystemService(NotificationManager.class); + if (manager != null) { + manager.createNotificationChannel(channel); + } } - Intent openAppIntent = new Intent(a, StreamerActivity.class); - PendingIntent openAppPendingIntent = PendingIntent.getActivity(a, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - Notification updatedNotification = new Notification.Builder(a, ZryteZenePlay.CHANNEL_ID) - .setContentTitle("ZryteZene") - .setContentText(b ? "Music is playing" : "Paused") - .setSmallIcon(android.R.drawable.ic_media_play) - .setContentIntent(openAppPendingIntent) - .addAction(actionIcon, actionTitle, actionPendingIntent) - .setOngoing(true) - .build(); - notificationManager.notify(ZryteZenePlay.NOTIFICATION_ID, updatedNotification); - } - public static void updateWithControls(Context a, boolean b) { - NotificationManager notificationManager = (NotificationManager) a.getSystemService(Context.NOTIFICATION_SERVICE); - if (notificationManager == null) return; + Intent playPauseIntent = new Intent(a, ZryteZenePlay.class).setAction(ZryteZenePlay.ACTION_BROADCAST).putExtra("action", b ? "pause" : "resume"); + Intent previousIntent = new Intent(a, ZryteZenePlay.class).setAction(ZryteZenePlay.ACTION_BROADCAST).putExtra("action", "previous"); + Intent nextIntent = new Intent(a, ZryteZenePlay.class).setAction(ZryteZenePlay.ACTION_BROADCAST).putExtra("action", "forward"); + PendingIntent playPausePendingIntent = PendingIntent.getService(a, 0, playPauseIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + PendingIntent previousPendingIntent = PendingIntent.getService(a, 0, previousIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + PendingIntent nextPendingIntent = PendingIntent.getService(a, 0, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - Intent playPauseIntent = new Intent(a, ZryteZenePlay.class); - playPauseIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - playPauseIntent.putExtra("action", b ? "pause" : "resume"); - PendingIntent playPausePendingIntent = PendingIntent.getService(a, 0, playPauseIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Intent previousIntent = new Intent(a, ZryteZenePlay.class); - previousIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - previousIntent.putExtra("action", "previous"); - PendingIntent previousPendingIntent = PendingIntent.getService(a, 1, previousIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Intent nextIntent = new Intent(a, ZryteZenePlay.class); - nextIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - nextIntent.putExtra("action", "forward"); - PendingIntent nextPendingIntent = PendingIntent.getService(a, 3, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Intent stopIntent = new Intent(a, ZryteZenePlay.class); - stopIntent.setAction(ZryteZenePlay.ACTION_BROADCAST); - stopIntent.putExtra("action", "stop"); - PendingIntent stopPendingIntent = PendingIntent.getService(a, 2, stopIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Intent openAppIntent = new Intent(a, StreamerActivity.class); - PendingIntent openAppPendingIntent = PendingIntent.getActivity(a, 0, openAppIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); - - Notification updatedNotification = new Notification.Builder(a, ZryteZenePlay.CHANNEL_ID) - .setContentTitle("ZryteZene") - .setContentText(b ? "Music is playing" : "Paused") - .setSmallIcon(android.R.drawable.ic_media_play) - .setContentIntent(openAppPendingIntent) + Notification nf; + if (f == null) { + nf = new NotificationCompat.Builder(a, ZryteZenePlay.CHANNEL_ID) + .setContentTitle(d) + .setContentText(e) + .setSmallIcon(R.drawable.ic_launcher) + .setStyle(new MediaStyle() + .setMediaSession(c.getSessionToken()) + .setShowActionsInCompactView(0, 1, 2)) .addAction(android.R.drawable.ic_media_previous, "Previous", previousPendingIntent) - .addAction(b ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play, b ? "Pause" : "Play", playPausePendingIntent) - .addAction(android.R.drawable.ic_menu_close_clear_cancel, "Stop", stopPendingIntent) + .addAction(b ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play, "Play/Pause", playPausePendingIntent) .addAction(android.R.drawable.ic_media_next, "Next", nextPendingIntent) + .setPriority(NotificationCompat.PRIORITY_LOW) .setOngoing(true) .build(); - notificationManager.notify(ZryteZenePlay.NOTIFICATION_ID, updatedNotification); + } else { + nf = new NotificationCompat.Builder(a, ZryteZenePlay.CHANNEL_ID) + .setContentTitle(d) + .setContentText(e) + .setSmallIcon(R.drawable.ic_launcher) + .setLargeIcon(f) + .setStyle(new MediaStyle() + .setMediaSession(c.getSessionToken()) + .setShowActionsInCompactView(0, 1, 2)) + .addAction(android.R.drawable.ic_media_previous, "Previous", previousPendingIntent) + .addAction(b ? android.R.drawable.ic_media_pause : android.R.drawable.ic_media_play, "Play/Pause", playPausePendingIntent) + .addAction(android.R.drawable.ic_media_next, "Next", nextPendingIntent) + .setPriority(NotificationCompat.PRIORITY_LOW) + .setOngoing(true) + .build(); + } + NotificationManager m = (NotificationManager) a.getSystemService(Context.NOTIFICATION_SERVICE); + if (m != null) { + m.notify(ZryteZenePlay.NOTIFICATION_ID, nf); + } } } diff --git a/app/src/main/java/tw/music/streamer/receiver/ZryteZeneBroadcastReceiver.java b/app/src/main/java/tw/music/streamer/receiver/ZryteZeneBroadcastReceiver.java new file mode 100644 index 0000000..e212457 --- /dev/null +++ b/app/src/main/java/tw/music/streamer/receiver/ZryteZeneBroadcastReceiver.java @@ -0,0 +1,48 @@ +package tw.music.streamer.receiver; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import tw.music.streamer.service.ZryteZenePlay; + +public class ZryteZeneBroadcastReceiver extends BroadcastReceiver { + + public static final String PLAY = "tw.music.streamer.ACTION_PLAY"; + public static final String PAUSE = "tw.music.streamer.ACTION_PAUSE"; + public static final String NEXT = "tw.music.streamer.ACTION_NEXT"; + public static final String PREVIOUS = "tw.music.streamer.ACTION_PREVIOUS"; + + @Override + public void onReceive(Context a, Intent b) { + if (b == null || b.getAction() == null) return; + + String c = b.getAction(); + Intent d = new Intent(a, ZryteZenePlay.class); + + switch (c) { + case PLAY: + d.putExtra("action", "play"); + break; + + case PAUSE: + d.putExtra("action", "pause"); + break; + + case NEXT: + d.putExtra("action", "next"); + break; + + case PREVIOUS: + d.putExtra("action", "previous"); + break; + + default: + Log.w("MusicBroadcastReceiver", "Unknown action: " + c); + return; + } + + a.startService(d); + } +} diff --git a/app/src/main/java/tw/music/streamer/service/ZryteZenePlay.java b/app/src/main/java/tw/music/streamer/service/ZryteZenePlay.java index 845ceb3..d4a88b1 100644 --- a/app/src/main/java/tw/music/streamer/service/ZryteZenePlay.java +++ b/app/src/main/java/tw/music/streamer/service/ZryteZenePlay.java @@ -16,6 +16,9 @@ import android.content.SharedPreferences; import androidx.annotation.Nullable; +//import androidx.media.session.MediaSessionCompat; + +import android.support.v4.media.session.MediaSessionCompat; import tw.music.streamer.notification.ZryteZeneNotification; @@ -24,22 +27,23 @@ public class ZryteZenePlay extends Service implements MediaPlayer.OnPreparedList public static final String ACTION_BROADCAST = "tw.music.streamer.ACTION"; public static final String ACTION_UPDATE = "tw.music.streamer.ACTION_UPDATE"; - public static final String CHANNEL_ID = "music_channel"; + public static final String CHANNEL_ID = "zrytezene_channel"; public static final int NOTIFICATION_ID = 2; private BroadcastReceiver br; private MediaPlayer mp; private IntentFilter ief; private SharedPreferences sp; - private String lm, act, csp; + private String lm, act, csp, sn, sa, sc; private Intent ita; private Handler ha = new Handler(); private boolean pd = false; + private MediaSessionCompat msc; @Override public void onCreate() { super.onCreate(); - initializePlayer(); + if (ief == null) initializePlayer(); } @Override @@ -56,6 +60,10 @@ public void onDestroy() { mp.release(); mp = null; } + if (msc!=null) { + msc.release(); + msc = null; + } super.onDestroy(); } @@ -80,6 +88,7 @@ private void initializePlayer() { startForeground(NOTIFICATION_ID, ZryteZeneNotification.setup(getApplicationContext())); sp = getSharedPreferences("teamdata", Activity.MODE_PRIVATE); lm = sp.getString("fvsAsc", ""); + msc = new MediaSessionCompat(getApplicationContext(), "ZryteZenePlay"); mp = new MediaPlayer(); br = new BroadcastReceiver() { @Override @@ -97,7 +106,7 @@ public void onReceive(Context a, Intent b) { public void onPrepared(MediaPlayer a) { a.start(); pd = true; - ZryteZeneNotification.update(getApplicationContext(), true); + ZryteZeneNotification.update(getApplicationContext(), true, msc, sn, sa, sc); tellActivity("on-prepared",a.getDuration()); ha.post(pr); } @@ -109,13 +118,13 @@ public void onBufferingUpdate(MediaPlayer a, int b) { @Override public void onCompletion(MediaPlayer a) { - ZryteZeneNotification.update(getApplicationContext(), "Idle..."); + ZryteZeneNotification.update(getApplicationContext(), false, msc, sn, sa, sc); tellActivity("on-completion","1"); } @Override public boolean onError(MediaPlayer a, int b, int c) { - ZryteZeneNotification.update(getApplicationContext(), "Idle..."); + ZryteZeneNotification.update(getApplicationContext(), false, msc, sn, sa, sc); tellActivity("on-error", String.format("Error(%s%s)", b, c)); return true; } @@ -158,7 +167,10 @@ private void applyMediaListener() { } private void playSong(Intent a) { - csp = a.getStringExtra("req-data"); + csp = a.getStringExtra("path"); + sn = a.getStringExtra("title"); + sa = a.getStringExtra("artist"); + sc = a.getStringExtra("cover"); if (mp != null) { mp.reset(); } else { @@ -179,7 +191,7 @@ private void pauseSong() { if (mp==null) return; if (mp.isPlaying()) { mp.pause(); - ZryteZeneNotification.update(getApplicationContext(), false); + ZryteZeneNotification.update(getApplicationContext(), false, msc, sn, sa, sc); tellActivity("request-pause"); } } @@ -188,7 +200,7 @@ private void resumeSong() { if (mp==null) return; if (isPrepared() && !mp.isPlaying()) { mp.start(); - ZryteZeneNotification.update(getApplicationContext(), true); + ZryteZeneNotification.update(getApplicationContext(), true, msc, sn, sa, sc); tellActivity("request-resume"); } } diff --git a/app/src/main/res/layout/stream_base.xml b/app/src/main/res/layout/stream_base.xml new file mode 100644 index 0000000..a6275af --- /dev/null +++ b/app/src/main/res/layout/stream_base.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + \ No newline at end of file