我是Android的初学者,现在正在制作音乐流媒体应用。为了初学者,我为Udemy学习了一门课程
教师一行一行地展示创作的每一步,我完全按照他的方式行事。现在我们已经到了创建通知的步骤
应用程序,他使用了一个名为'NotificationCompat.Builder(this)'
的东西。现在,当我键入相同的确切代码时,我得到一个错误,说明了
{O}现在已经在Android O中被弃用了。由于这个原因,我在手机上没有收到通知
运行。音乐也没有流式传输。由于这个原因,我无法继续进一步的讲座。
我试图向论坛上的讲师询问有关此问题的一些帮助,但他似乎没有回复。我也试着去研究
关于android O中的通知通道,但由于缺乏基本的android知识,我无法理解这些概念。
如果我能就我的问题得到一些帮助,那就太棒了。
我正在上传我的代码。
错误发生在NotificationCompat.Builder(context)
(1)。 activity_main.xml中
PlayerService.java
(2)。 MainActivity.java
<?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>
(3)。 PlayerService.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);
}
}
(4)。 Player.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");
}
}
}
(5)。 Constants.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");
}
}
}
(6)。的AndroidManifest.xml
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;
}
}
答案 0 :(得分:2)
为了方便Android Oreo中名为Notification Channels的新功能,不推荐使用上一种方法。
通知渠道允许我们根据预期行为对通知进行分组。因此,每当用户不需要查看特定类型的通知时,他们就可以禁用相应的通道。
例如,考虑一个电子商务应用程序。它显示促销/优惠,订单状态等的通知。促销和优惠通知分组到名为“促销”的频道中。因此,如果用户不希望仅看到这些通知,则可以从应用设置中禁用“促销”频道。
如果您使用已弃用的方法,则通知将在Oreo中以静默方式失败。要使其工作,请使用新的Builder构造函数。更改您的代码如下:
Notification notification=new NotificationCompat.Builder(this, CHANNEL_ID)
// set title, message, etc.
.build();
为奥利奥创建一个这样的通知渠道:
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);
}