Reputation: 15
I am a beginner in android and right now working on a music streaming app. I have taken a course on Udemy for beginners for that and
the instructor goes line by line showing each step of creation,and i do exactly what he does. Now that we have reached the step of creating a notification for the
app, he uses something called 'NotificationCompat.Builder(this)'
. Now when I type the same exact code, I get an error saying that the
NotificationCompat.Builder(context)
has been deprecated now in android O. Due to this I am not getting the notifications on my phone when I
run it. Also the music is not being streamed. Due to this I am not able to proceed with further lectures.
I tried to ask the instructor on the forum for some help regarding this, but he does not seem to reply back. Also I tried to research
about the notification channels in android O, but I am unable to understand the concepts due to the lack of knowledge on basic android.
So it would be great if I could get some help regarding my problem.
I am uploading my code along with this.
The error is in PlayerService.java
(1). activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.music.zirakmistry.musicstreamingapp.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
app:srcCompat="@android:drawable/ic_media_play" />
</android.support.design.widget.CoordinatorLayout>
(2). MainActivity.java
public class MainActivity extends AppCompatActivity {
static FloatingActionButton playPauseButton;
PlayerService mBoundService;
boolean mServiceBound=false;
private ServiceConnection mServiceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
PlayerService.MyBinder myBinder=(PlayerService.MyBinder)service;
mBoundService=myBinder.getService();
mServiceBound=true;
}
@Override
public void onServiceDisconnected(ComponentName name){
mServiceBound=false;
}
};
private BroadcastReceiver mMessageReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
boolean isPlaying=intent.getBooleanExtra("isPlaying",false);
flipPlayPauseButton(isPlaying);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
playPauseButton = (FloatingActionButton) findViewById(R.id.fab);
playPauseButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view){
if(mServiceBound)
mBoundService.togglePlayer();
}
});
startStreamingService("https://www.mymusicstreamingapp.com/music_app/cute.mp3");
}
private void startStreamingService(String url)
{
Intent i=new Intent(this,PlayerService.class);
i.putExtra("url",url);
i.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(i);
bindService(i,mServiceConnection,Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if(mServiceBound){
unbindService(mServiceConnection);
mServiceBound=false;
}
}
@Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("changePlayButton"));
}
@Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
public static void flipPlayPauseButton(boolean isPlaying){
if(isPlaying){
playPauseButton.setImageResource(android.R.drawable.ic_media_pause);
}
else{
playPauseButton.setImageResource(android.R.drawable.ic_media_play);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
(3). PlayerService.java
public class PlayerService extends Service {
MediaPlayer mediaPlayer=new MediaPlayer();
private final IBinder mBinder=new MyBinder();
public class MyBinder extends Binder
{
PlayerService getService()
{
return PlayerService.this;
}
}
public PlayerService()
{
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
if(intent.getStringArrayExtra("url")!=null)
playStream(intent.getStringExtra("url"));
if(intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION))
{
Log.i("info","Start foregroung service");
showNotification();
}
else if(intent.getAction().equals(Constants.ACTION.PREV_ACTION))
{
Log.i("info","Prev pressed");
}
else if(intent.getAction().equals(Constants.ACTION.PLAY_ACTION))
{
Log.i("info","Play pressed");
}
else if(intent.getAction().equals(Constants.ACTION.NEXT_ACTION))
{
Log.i("info","Next pressed");
}
else if(intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION))
{
Log.i("info","Stop foreground received");
stopForeground(true);
stopSelf();
}
return START_REDELIVER_INTENT;
}
private void showNotification()
{
Intent notificationIntent=new Intent(this,MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags((Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
PendingIntent pendingIntent=PendingIntent.getActivity(this,0,notificationIntent,0);
Intent previousIntent=new Intent(this,MainActivity.class);
previousIntent.setAction(Constants.ACTION.PREV_ACTION);
PendingIntent ppreviousIntent=PendingIntent.getActivity(this,0,previousIntent,0);
Intent playIntent=new Intent(this,MainActivity.class);
playIntent.setAction(Constants.ACTION.PLAY_ACTION);
PendingIntent pplayIntent=PendingIntent.getActivity(this,0,playIntent,0);
Intent nextIntent=new Intent(this,MainActivity.class);
nextIntent.setAction(Constants.ACTION.NEXT_ACTION);
PendingIntent pnextIntent=PendingIntent.getActivity(this,0,nextIntent,0);
Bitmap icon= BitmapFactory.decodeResource(getResources(),R.drawable.logo);
Notification notification=new NotificationCompat.Builder(this)
.setContentTitle("Music Player")
.setTicker("Playing music")
.setContentText("My Song")
.setSmallIcon(R.drawable.logo)
.setLargeIcon(Bitmap.createScaledBitmap(icon,128,128,false))
.setContentIntent(pendingIntent)
.setOngoing(true)
.addAction(android.R.drawable.ic_media_previous,"Previous",ppreviousIntent)
.addAction(android.R.drawable.ic_media_play,"Play",pplayIntent)
.addAction(android.R.drawable.ic_media_next,"Next",pnextIntent)
.build();
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,notification);
}
@Override
public IBinder onBind(Intent intent)
{
return mBinder;
}
public void playStream(String url)
{
if(mediaPlayer!=null)
{
try
{
mediaPlayer.stop();
}
catch(Exception e)
{
}
mediaPlayer=null;
}
mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try
{
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer mp)
{
playPlayer();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mp)
{
flipPlayPauseButton(false);
}
});
mediaPlayer.prepareAsync();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void pausePlayer()
{
try
{
mediaPlayer.pause();
flipPlayPauseButton(false);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void playPlayer()
{
try
{
mediaPlayer.start();
flipPlayPauseButton(true);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void flipPlayPauseButton(boolean isPlaying)
{
// code to communicate with main thread
Intent intent=new Intent("changePlayButton");
//add data
intent.putExtra("isPlaying",isPlaying);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
public void togglePlayer()
{
try
{
if(mediaPlayer.isPlaying())
pausePlayer();
else
playPlayer();
}
catch(Exception e)
{
Log.d("Exception","failed to toggle media player");
}
}
}
(4). Player.java
public class Player {
MediaPlayer mediaPlayer=new MediaPlayer();
public static Player player;
String url="";
public Player()
{
this.player = this;
}
public void playStream(String url)
{
if(mediaPlayer!=null)
{
try
{
mediaPlayer.stop();
}
catch(Exception e)
{
}
mediaPlayer=null;
}
mediaPlayer=new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
try
{
mediaPlayer.setDataSource(url);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
{
@Override
public void onPrepared(MediaPlayer mp)
{
playPlayer();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
{
@Override
public void onCompletion(MediaPlayer mp)
{
MainActivity.flipPlayPauseButton(false);
}
});
mediaPlayer.prepareAsync();
}
catch(IOException e)
{
e.printStackTrace();
}
}
public void pausePlayer()
{
try
{
mediaPlayer.pause();
MainActivity.flipPlayPauseButton(false);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void playPlayer()
{
try
{
mediaPlayer.start();
MainActivity.flipPlayPauseButton(true);
}
catch(Exception e)
{
Log.d("EXCEPTION","failed to pause media player");
}
}
public void togglePlayer()
{
try
{
if(mediaPlayer.isPlaying())
pausePlayer();
else
playPlayer();
}
catch(Exception e)
{
Log.d("Exception","failed to toggle media player");
}
}
}
(5). Constants.java
public class Constants {
public interface ACTION {
public static String MAIN_ACTION="com.music.zirakmistry.musicstreamingapp.action.main";
public static String PREV_ACTION="com.music.zirakmistry.musicstreamingapp.action.prev";
public static String PLAY_ACTION="com.music.zirakmistry.musicstreamingapp.action.play";
public static String NEXT_ACTION="com.music.zirakmistry.musicstreamingapp.action.next";
public static String STARTFOREGROUND_ACTION="com.music.zirakmistry.musicstreamingapp.action.startforeground";
public static String STOPFOREGROUND_ACTION="com.music.zirakmistry.musicstreamingapp.action.stopforeground";
}
public interface NOTIFICATION_ID
{
public static int FOREGROUND_SERVICE=101;
}
}
(6). AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.music.zirakmistry.musicstreamingapp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".PlayerService"
android:enabled="true"
android:exported="true" />
</application>
</manifest>
Upvotes: 0
Views: 3236
Reputation: 1715
In order to facilitate the new feature called Notification Channels in Android Oreo the previous method was deprecated.
Notification Channels allow us to group notifications based on their intended behavior. So whenever a user don't need to see a specific type of notification they can disable the corresponding channel.
So for example consider an e-commerce app. It shows notifications for promotions/offers, order status, etc. Promotion and offer notifications are grouped into a channel named "promotion". So if the user don't want to see only these notifications they can disable the "promotion" channel from the app settings.
If you use the deprecated method, the notification will fail silently in Oreo. To make it work, use the new Builder constructor. Change your code as below:
Notification notification=new NotificationCompat.Builder(this, CHANNEL_ID)
// set title, message, etc.
.build();
And create a notification channel like this for Oreo:
NotificationManager manager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Support for Android Oreo: Notification Channels
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"Channel_name_to_be_displayed_in_Settings",
NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel(channel);
}
Upvotes: 4