Notification和Activity交互

概述

通知(Notification)就是程序在不影响用户操作的情况下,通过手机顶部弹出消息告诉用户的一种信息通知方式,并且可以通过下拉通知操作抽屉通知,实现Notification与活动、通知和服务通信。例如:通知与活动相互通信,活动通过NotificationManager发送通知(创建通知),而抽屉通知里面的操作则通过发送广播事件传递信息,此时活动只要已经注册过该广播事件的接收器,那么就能接收到通知的信息,从而实现通知和活动交互。

例子(通知和活动同步音乐播放和暂停)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <FrameLayout android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@drawable/bg"
            android:scaleType="fitXY"/>

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/play_over"
            android:layout_gravity="center"
            android:clickable="true"
            android:id="@+id/imageView"
            android:background="@drawable/img_bg"/>

    </FrameLayout>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="64dp"
    android:background="#e0e0e0"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:src="@drawable/sc"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ImageView
        android:id="@+id/image_control"
        android:clickable="true"
        android:padding="4dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:src="@drawable/play_over"/>

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/image_control"
            android:padding="4dp"
            android:text="Sweet Child O' Mine"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceMedium"/>

      	<TextView
      	    android:id="@+id/tv_nowTime"
      	    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@id/image_control"
            android:text="00:00"
            android:layout_alignParentBottom="true"/>

      	<TextView
      	    android:id="@+id/tv_totallTime"
      	    android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentBottom="true"
            android:text="00:00"/>

    </RelativeLayout>

</LinearLayout>
package com.liujun.activity;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import com.liujun.liujunmusicnotification.R;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.RemoteViews;

public class MainActivity extends Activity {

	private MediaPlayer mediaPlayer;//媒体播放器

	private NotificationManager notificationManager;//通知管理器

	private ImageView imageView;//播放音乐图片按钮

	private boolean isPlaying=false;//是否正在播放音乐

	//意图
	public static final String PLAYMUSIC_INTENT="PLAYMUSIC_INTENT";
	public static final String PAUSEMUSIC_INTENT="PAUSEMUSIC_INTENT";

	//通知标识ID
	public static final int NOTIFICATION_ID=1;

	//时间计时器
	private Timer timer;

	private MyBroadCastRecever recever;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mian_activity);

		//实例化媒体播放器
		mediaPlayer=MediaPlayer.create(this, R.raw.sc);

		//实例化通知管理器
		notificationManager=(NotificationManager) this.getSystemService(NOTIFICATION_SERVICE);

		timer=new Timer();

		imageView=(ImageView) this.findViewById(R.id.imageView);
		imageView.setOnClickListener(onClickListener);

		//注册接收通知栏发送的广播事件
		IntentFilter intentFilter=new IntentFilter();
		intentFilter.addAction(PAUSEMUSIC_INTENT);
		intentFilter.addAction(PLAYMUSIC_INTENT);

		recever=new MyBroadCastRecever();

		this.registerReceiver(recever, intentFilter);
	}

	OnClickListener onClickListener=new OnClickListener() {

		@Override
		public void onClick(View v) {

			if (!isPlaying) {//没有播放音乐

				//开始播放音乐
				playMusic();

				//更改图片背景
				imageView.setImageResource(R.drawable.pause_over);

				//更改标志
				isPlaying=true;

			}else {//正在播放音乐

				//暂停播放音乐
				pauseMusic();

				//更改图片背景
				imageView.setImageResource(R.drawable.play_over);

				//更改标志
				isPlaying=false;

			}

			//发送通知栏
			activitySendNotification();

		}
	};

	/**
	 * 播放音乐
	 */
	protected void playMusic() {

		if (mediaPlayer==null) {

			mediaPlayer=MediaPlayer.create(MainActivity.this, R.raw.sc);
		}

		if (timer==null) {

			timer=new Timer();

		}

		//开启计时器任务,每个一秒 更新抽屉通知音乐播放进度
		timer.schedule(new MyTimerTask(), 0, 1000);

		//播放音乐
		mediaPlayer.start();

	}

	//时间任务,更新抽屉通知,播放进度(注意:每次调用必须重新new)
	private class MyTimerTask extends TimerTask{

		@Override
		public void run() {

			//活动端发送通知
			activitySendNotification();
		}

	}

	/**
	 * 发送通知
	 */
	protected void activitySendNotification() {

		//通知构建器
		NotificationCompat.Builder builder=new NotificationCompat.Builder(this); 

		//设置小图标
		builder.setSmallIcon(R.drawable.favorite);

		//加载自定义远程布局
		RemoteViews remoteView=(RemoteViews) new RemoteViews(this.getPackageName(), R.layout.my_notification);

		//设置不可以拉动取消抽屉通知
		builder.setOngoing(true);

		//设置标题
		remoteView.setTextViewText(R.id.tv_title, "Sweet Child O' Mine");

		//当前播放时间(注意:当进入界面播放音乐时退出界面,不是暂停时退出界面,那么就有可能在程序执行
		//onDestroy()方法时将mediaPlayer释放并置空了,而此段代码是在子线程中的,与主线程不同步退出,
		//那么就导致mediaPlayer为空,从而报错)
		if (mediaPlayer==null) {
			return;
		}

		Date currentDate=new Date(mediaPlayer.getCurrentPosition());

		//总时长
		Date totalDate=new Date(mediaPlayer.getDuration());

		SimpleDateFormat simpleDateFormat=new SimpleDateFormat("mm:ss");

		//设置当前播放时间进度
		remoteView.setTextViewText(R.id.tv_nowTime, simpleDateFormat.format(currentDate));

		//设置歌曲总时长
		remoteView.setTextViewText(R.id.tv_totallTime, simpleDateFormat.format(totalDate));

		Log.i("liujun", "是否正在播放音乐:--"+isPlaying);

		if (isPlaying) {//正在播放音乐

			//显示可以暂停图片
			remoteView.setImageViewResource(R.id.image_control, R.drawable.pause_over);

		}else {

			//显示可以播放图片
			remoteView.setImageViewResource(R.id.image_control, R.drawable.play_over);
		}

		//通知栏,交互互动
		notificationToActivity(remoteView,isPlaying);

		//加载视图布局
		builder.setContent(remoteView);

		//创建通知
		Notification notification=builder.build();

		//发送通知
		notificationManager.notify(NOTIFICATION_ID, notification);

	}

	/**
	 * 通知栏交互活动
	 * @param isPlaying
	 */
	private void notificationToActivity(RemoteViews remoteView,boolean isPlaying) {

		Intent intent=new Intent();

		if (isPlaying) {//正在播放音乐

			//试图暂停播放音乐
			intent.setAction(PAUSEMUSIC_INTENT);

			//更改图片
			remoteView.setImageViewResource(R.id.image_control, R.drawable.pause_over);

		/*	//更新标志
			isPlaying=false;*/

		}else {//没有播放音乐

			//试图播放音乐
			intent.setAction(PLAYMUSIC_INTENT);

			//更改图片
			remoteView.setImageViewResource(R.id.image_control, R.drawable.play_over);

			/*//更新标志
			isPlaying=true;*/
		}

		//发送广播,更新Activity
		PendingIntent pendingIntent=PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

		remoteView.setOnClickPendingIntent(R.id.image_control, pendingIntent);

	}

	//广播接收器(接收通知发送的广播事件)
	private class MyBroadCastRecever extends BroadcastReceiver{

		@Override
		public void onReceive(Context context, Intent intent) {

			if (intent.getAction()==PLAYMUSIC_INTENT) {//通知端播放音乐

				//播放音乐
				playMusic();

				//是否播放正在播放音乐标志
				isPlaying=true;

				//更改图片标志
				imageView.setImageResource(R.drawable.pause_over);

			}else if(intent.getAction()==PAUSEMUSIC_INTENT){//通知端暂停音乐

				//暂停音乐
				pauseMusic();

				//是否播放正在播放音乐标志
				isPlaying=false;

				//更改图片标志
				imageView.setImageResource(R.drawable.play_over);

			}

			//上面更新活动的信息,这时又要发送通知
			activitySendNotification();

		}

	}

	/**
	 * 暂停播放音乐
	 */
	protected void pauseMusic() {

		if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {

			mediaPlayer.pause();
		}

		//暂停发送通知
		if (timer!=null) {
			timer.cancel();
			timer=null;
		}

	}

	@Override
	protected void onDestroy() {

		super.onDestroy();

		this.unregisterReceiver(recever);

		//释放资源
		if (mediaPlayer!=null) {

			mediaPlayer.release();

			mediaPlayer=null;
		}

		//是否通知栏
		notificationManager.cancel(NOTIFICATION_ID);

	}

}

时间: 2024-10-10 07:09:05

Notification和Activity交互的相关文章

深入分析:Fragment与Activity交互的几种方式(一,使用Handler)

这里我不再详细介绍那写比较常规的方式,例如静态变量,静态方法,持久化,application全局变量,收发广播等等. 首先我们来介绍使用Handler来实现Fragment与Activity 的交互. 第一步,我们需要在Activity中定义一个方法用来设置Handler对象. public void setHandler(Handler handler) { mHandler = handler; } 第二步,在Fragment中的回调函数onAttach()中得到Fragment所在Acti

深入分析:Fragment与Activity交互的几种方式(三,使用接口)

第一步:我们需要在Fragment中定一个接口,并确保我们的容器Activity实现了此接口: public interface onTestListener { public void onTest(String str); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // 这个方法是用来确认当前的Activity容器是否已经继承了该接口,如果没有将抛出异常 try { mCal

Fragment与Activity交互(使用接口)

在Fragment中: 1. // 定义一个回调接口,该Fragment所在Activity需要实现该接口// 该Fragment将通过该接口与它所在的Activity交互 { public void onItemSelected(Integer id);} 2. // 当该Fragment被添加.显示到Activity时,回调该方法 public void onAttach(Activity activity){ super.onAttach(activity); // 如果Activity没

android开发之使用Messenger实现service与activity交互

service与activity交互的方式有多种,这里说说使用Messenger来实现两者之间的交互. Service程序 public class MessengerService extends Service { final Messenger mMessenger = new Messenger(new IncomingHandler()); @Override public IBinder onBind(Intent intent) { return mMessenger.getBin

Fragment与Activity交互(使用Handler)

1.在Activity中定义一个方法用来设置Handler对象 public void setHandler(Handler handler) {mHandler = handler;} 2.在Fragment中的回调函数onAttach()中得到Fragment所在的Activity,并调用setHandler方法,设置Handler.该Handler在Fragment中定义,用来接收来自Activity的消息 @Overridepublic void onAttach(Activity ac

android Fragment与Activity交互,互相发数据(附图具体解释)

笔者最近看官方training.发现了非常多实用又好玩的知识. 当中.fragment与Activity通信就是一个. fragment与Activity通信主要是两点: 1.fragment传递信息给Activity 此点是通过在fragment中定义接口与Activity共享数据. 2.Activity传递信息给fragment 此点主要是通过fragment的getArgument()和setArgument()两个函数传递bundle来传递. 效果:(最后附上源代码) 主要流程: 1.在

Fragment与Activity交互

尽管Fragment被实现为一个对象,它独立于Activity并可以在多个Activity中使用,一个给定的fragment实例直接被捆绑在包含它的Activity中. 特别是,fragment可以通过getActivity()函数访问Activity,并且很容易的执行类似于查找activity布局中的视图的任务:  View listView = getActivity().findViewById(R.id.list); 同样的,activity能够调用fragment的函数findFrag

Service和Activity交互之广播方式

一.使用场景如果要通知多个Activity,广播较为适合.但广播较为耗费性能. 二.Broadcast更新Activity中的UI 1.新建一个接口OnUpdateUI public interface OnUpdateUI { void updateUI(String i); } 2.BroadcastReceiver代码 public class MyBroadcast extends BroadcastReceiver { OnUpdateUI onUpdateUI; @Override

android Service Activity交互之传递复杂数据类型的远程服务

远程服务往往不只是传递java基本数据类型.这时需要注意android的一些限制和规定: android支持String和CharSequence 如果需要在aidl中使用其他aidl接口类型,需要import,即使是在相同包结构下: android允许传递实现Parcelable接口的类,需要import: android支持集合接口类型List和Map,但是有一些限制,元素必须是基本型或者上述三种情况,不需要import集合接口类,但是需要对元素涉及到的类型import: 非基本数据类型,也