在自定义Notification中启动服务、打开App的简单案例(学习笔记)

本文介绍了一个基于安卓的音乐播放服务实现,详细解释了如何使用MediaPlayer类播放固定mp3文件,以及如何在通知栏中显示播放控制。通过创建MusicService类,结合FragmentManager和NotificationManager,实现了音乐播放控制和后台运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为了让案例代码简单易懂,本案例虽然是以播放音乐功能进行演示,但是为了减少代码量,让演示功能可以更直观地理解,本案例只选取一首固定的mp3进行操作演示,但播放mp3使用了安卓内置的MediaPlayer类,该类可以胜任音频和视频的播放,如果想详细了解,请查阅该类的技术文档。

先添加音乐服务类MusicService 继承 Service
因为是简单的播放功能 所以用MediaPlayer

public class MusicService extends Service {
private MediaPlayer mediaPlayer;

public MusicService() {//此构造方法必须写 要不然会报错
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}//可以自己定义 IBinder 用来调用方法 通信

@Override
public void onCreate() {
    super.onCreate();
    this.mediaPlayer = MediaPlayer.create(this,R.raw.xinghe);//创建
    this.mediaPlayer.start();//播放
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {//开启服务
    Log.d("TAG", "onStartCommand: " + intent.getAction());
    if (intent.getAction()!=null&&intent.getAction().equals("STOP")){
        this.mediaPlayer.pause();


    }
    if (intent.getAction()!=null&&intent.getAction().equals("EXIT")){
        System.exit(0);
    }

    if (intent.getAction()!=null&&intent.getAction().equals("START")) {
        this.mediaPlayer.start();
    }
    return START_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    this.mediaPlayer.stop();
}
}

然后要在 manifest中添加 (不添加服务类无法使用)

<service android:name=".MusicService">
        <intent-filter>
            <action android:name="com.example.mymusic.MusicPlayer"></action>
        </intent-filter>
    </service>

然后为通知栏新建一个布局文件(不能太复杂 尽量简洁 要不然通知栏显示不出来)
在这里插入图片描述

然后新建一个MusicFragment继承Fragment
把刚刚新建的 layout和MusicFragment绑定
public class MusicFragment extends Fragment {
private View view;
private Intent svc_intent;
public boolean isplay = false;
private Context context;

private ServiceConnection sc = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {

    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
};

public boolean isIsplay() {
    return isplay;
}

public void setIsplay(boolean isplay) {
    this.isplay = isplay;
}

public MusicFragment(Context context){
    svc_intent = new Intent(context,MusicService.class);
    svc_intent.setPackage("com.example.mymusic");
    this.context = context;
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.notification,container,false);
    TextView textViewMusicName = view.findViewById(R.id.textViewMusicName);
    final ImageView btnPlay = view.findViewById(R.id.imageViewPlay);
    ImageView btnMusic = view.findViewById(R.id.imageViewMusic);
    ImageView btnClose = view.findViewById(R.id.imageViewClose);


    btnMusic.setVisibility(View.GONE);
    btnClose.setVisibility(View.GONE);

    textViewMusicName.setText("刘佳怡 - 所念皆星河(纯钢琴)(翻自 CMJ) .mp3");

    btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (isplay){
                isplay =false;
                svc_intent.setAction("STOP");
                btnPlay.setImageResource(R.drawable.ic_play_circle_outline_black_24dp);
                context.startService(svc_intent);

            }
            else {
                svc_intent.setAction("START");
                btnPlay.setImageResource(R.drawable.ic_pause_circle_outline_black_24dp);
                getActivity().bindService(svc_intent,sc, Service.BIND_AUTO_CREATE);
                context.startService(svc_intent);

                isplay = true;

            }


        }
    });

    view.findViewById(R.id.imageViewStop).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            getActivity().unbindService(sc);
        }
    });
    return view;
}
}

然后布局Mainlayout
在这里插入图片描述
container是用来盛放musicfragment的

MainActivity中的

    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    notifManager.cancelAll();//清除所有通知
    Intent intent = new Intent(this,MusicService.class);
    //stopService(intent);//停止音乐服务
    CreatChannle();//创建频道
    createNotification();//创建通知栏
    musicFragment = new MusicFragment(this);
    getSupportFragmentManager().beginTransaction().replace(R.id.container, musicFragment).commit();
}
  @Override
public void onBackPressed() {
    onStop();
}//重写返回按键

@Override
protected void onStop() {
    super.onStop();
    confirmExitRuning();//弹确认退出对话框
}

只有高版本才需要创建(API大于26)

//创建广播评到设置重要性
private void CreatChannle(){

    if (notifManager == null)
        notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

    if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){
        //将通知重要性设为低,这样就不会有通知的声音(部分模拟器仍然会发声)
        int importance = NotificationManager.IMPORTANCE_LOW;

        mChannel = notifManager.getNotificationChannel(Channel_ID);
        if (mChannel==null){
            mChannel = new NotificationChannel(Channel_ID,ChannelName,importance);
            mChannel.setDescription(Channel_Description);
            notifManager.createNotificationChannel(mChannel);
        }
    }
}

该函数设置通知栏的视图内容,包括布局和布局内四个按钮的点击事件处理
private RemoteViews getRemoteView(){

    RemoteViews remoteViews = new RemoteViews(getPackageName(),R.layout.notification);
    remoteViews.setTextViewText(R.id.textViewMusicName,noteMessage);
    remoteViews.setImageViewResource(R.id.imageViewMusic,R.drawable.ic_music_note_black_24dp);
    remoteViews.setImageViewResource(R.id.imageViewClose,R.drawable.ic_close_black_24dp);
    remoteViews.setImageViewResource(R.id.imageViewStop,R.drawable.ic_stop_black_24dp);
    remoteViews.setImageViewResource(R.id.imageViewPlay,R.drawable.ic_play_circle_outline_black_24dp);

   //播放按钮打开服务
    Intent intent  =new Intent(MainActivity.this,MusicService.class);
    intent.setAction("START");

    PendingIntent pendingIntent = PendingIntent.getService(this,0,intent,0);
    remoteViews.setOnClickPendingIntent(R.id.imageViewPlay,pendingIntent);

    //停止按钮打开服务(设置停止标签)
    Intent intentStop  =new Intent(MainActivity.this,MusicService.class);
    intentStop.setAction("STOP");

    PendingIntent pendingIntentStop = PendingIntent.getService(this,0,intentStop,0);

    remoteViews.setOnClickPendingIntent(R.id.imageViewStop,pendingIntentStop);

    //关闭广播和服务
    Intent intent_close = new Intent(this,CloseNotificationReceiver.class);
    PendingIntent pendingIntent_close = PendingIntent.getBroadcast(this,0,intent_close,0);
    remoteViews.setOnClickPendingIntent(R.id.imageViewClose,pendingIntent_close);

    //打开app
    Intent intent_open = new Intent(getApplicationContext(),MainActivity.class);
    PendingIntent pendingIntent_open = PendingIntent.getActivity(getApplicationContext(),0,intent_open,PendingIntent.FLAG_UPDATE_CURRENT);
    remoteViews.setOnClickPendingIntent(R.id.imageViewMusic,pendingIntent_open);



    return remoteViews;

}

用于关闭通知和服务的静态内部广播类
必须在mainframe中添加

 <receiver
        android:name=".MainActivity$CloseNotificationReceiver"
        android:enabled="true"
        android:exported="true"/>

然后是类
public static class CloseNotificationReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("TAG", "onReceive: ");
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancelAll();
        Intent musicSvc = new Intent(context,MusicService.class);
        context.stopService(musicSvc);
        System.exit(0);
    }
}

创建通知栏 要分三种情况 API<19 19<API<26 API>26

 public void createNotification(){
    Intent intent = new Intent(MainActivity.this,MusicService.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getService(MainActivity.this,0,intent,0);
    noteMessage ="刘佳怡 - 所念皆星河(纯钢琴)(翻自 CMJ) .mp3";
    if (Build.VERSION.SDK_INT<Build.VERSION_CODES.JELLY_BEAN){
        //使用 NotificationCompat 而不是Notification,因为Notification需要API16才能使用
        //NotificationCompat 存在于V4 Support Library
        NotificationCompat.Builder compat_builder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(note_Title)
                .setContentText(noteMessage)
                .setAutoCancel(false)
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pendingIntent);

        if (compat_builder != null){
            //设置通知栏的视图内容
            compat_builder.setContent(getRemoteView());
            if (notifManager == null){
                notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            }

            notifManager.notify(NOTE_ID,compat_builder.build());
        }

    }else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN&&Build.VERSION.SDK_INT<Build.VERSION_CODES.O){
        Notification.Builder notificationBuilder = new Notification.Builder(MainActivity.this);
        notificationBuilder.setSmallIcon(R.drawable.ic_music_note_black_24dp);
        notificationBuilder.setContentTitle(note_Title);
        notificationBuilder.setContentText(noteMessage);
        notificationBuilder.setAutoCancel(false);
        notificationBuilder.setOngoing(true);
        notificationBuilder.setWhen(System.currentTimeMillis());
        notificationBuilder.setContentIntent(pendingIntent);

        if (notificationBuilder != null){
            //设置通知栏的视图内容
            notificationBuilder.setContent(getRemoteView());
            if (notifManager == null){
                notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            }
            notifManager.notify(NOTE_ID,notificationBuilder.build());
        }
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
            Notification.Builder notificationBuilder =null;
             notificationBuilder=
                    new Notification.Builder(getApplicationContext(),Channel_ID)
                .setSmallIcon(R.drawable.ic_music_note_black_24dp)
                .setContentTitle(note_Title)
                .setContentText(noteMessage)
                .setAutoCancel(false)
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setContentIntent(pendingIntent);

        if (notificationBuilder != null){
            //设置通知栏的视图内容
            notificationBuilder.setContent(getRemoteView());
            if (notifManager == null){
                notifManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

            }
            if (notifManager != null){
                notifManager.notify(NOTE_ID,notificationBuilder.build());

            }

        }
    }
}

//确认对话框

private void confirmExitRuning() {
    new AlertDialog.Builder(MainActivity.this)
            .setIcon(R.drawable.ic_warning_black_24dp)
            .setTitle("退出提示")
            .setMessage("要在后台运行吗?")
            .setPositiveButton("后台运行", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    createNotification();
                    goToDesktop(MainActivity.this);
                   // System.exit(0);
                }
            })
            .setNegativeButton("直接退出!", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent(getApplicationContext(),MusicService.class);
                    stopService(intent);
                    System.exit(0);
                }
            }).create().show();
}

返回到桌面

public static void goToDesktop(Context context) {
    Intent intent = new Intent(Intent.ACTION_MAIN);
    intent.addCategory(Intent.CATEGORY_HOME);
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    context.startActivity(intent);
}

然后九世最终效果了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值