桌面widget詳解(二)—— 基本的與service通信

因爲我們的widget是沒有辦法像Activity一樣根據ID獲取到View對象的,所以根本沒有辦法在widget代碼中直接操作,只能通過Service來間接交互操作(看不懂沒關係,下篇會具體講);如果我一上來就講如何與Service交互,大家可能一頭霧水。因爲Service本身就不是個簡單的東東。所以我先岔開話題,講講我們如何在MainActivity中實現一個音樂播放器的雛形。這篇主要在於理解Service的機制與如何與Service交互的問題。
 

看一下效果圖:

點擊開始btn,開始播放歌曲,並顯示當前播放歌曲的id號,然後點擊上一首,下一首按鈕時播放序列中的上一首或者下一首歌,並實時更新當前的歌曲ID;

一、播放歌曲的Service(MusicManageService)

首先,我們先放工程裏九首歌,放在res/raw文件夾下。

現在有的音樂文件以後,我們要在service裏實現一個歌曲文件的列表,以及播放上一首,一下首的功能。

先貼出完整的代碼,然後再逐步講解。

public class MusicManageService extends Service {
 
	private MediaPlayer mPlayer;
	private int mIndex = 4;// 從中間開始放
	private int[] mArrayList = new int[9];
 
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
 
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
 
		initList();
		mediaPlayerStart();		
	}
	
	private void initList() {
		mArrayList[0] = R.raw.dui_ni_ai_bu_wan;
		mArrayList[1] = R.raw.fei_yu;
		mArrayList[2] = R.raw.gu_xiang_de_yun;
		mArrayList[3] = R.raw.hen_ai_hen_ai_ni;
		mArrayList[4] = R.raw.new_day;
		mArrayList[5] = R.raw.shi_jian_li_de_hua;
		mArrayList[6] = R.raw.ye_gui_ren;
		mArrayList[7] = R.raw.yesterday_once_more;
		mArrayList[8] = R.raw.zai_lu_shang;
	}
	
	private void mediaPlayerStart(){
		mPlayer = new MediaPlayer();
		mPlayer = MediaPlayer.create(getApplicationContext(), mArrayList[mIndex]);
		mPlayer.start();
	}
 
	@Override
	public void onDestroy() {
 
		super.onDestroy();
		mPlayer.stop();
	}
 
	/**
	 * 播放下一首
	 * 
	 * @param context
	 */
	public void playNext(Context context) {
		if (++mIndex > 8) {
			mIndex = 0;
		}
		playSong(context, mArrayList[mIndex]);
	}
 
	/**
	 * 播放上一首
	 * 
	 * @param context
	 */
	public void playPrev(Context context) {
		if (--mIndex < 0) {
			mIndex = 8;
		}
		playSong(context, mArrayList[mIndex]);
	}
 
	/*
	 * 繼續播放
	 */
	public void play(Context context) {
		mPlayer.start();
	}
 
	/**
	 * 暫停播放
	 * 
	 * @param context
	 */
	public void pause(Context context) {
		mPlayer.pause();		
	}
 
	/**
	 * 播放指定的歌曲
	 * 
	 * @param context
	 * @param resid
	 */
	private void playSong(Context context, int resid) {
		
		AssetFileDescriptor afd = context.getResources().openRawResourceFd(mArrayList[mIndex]);
		try {
			mPlayer.reset();
			mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getDeclaredLength());
			mPlayer.prepare();
			mPlayer.start();
			afd.close();
		} catch (Exception e) {
			Log.e("harvic","Unable to play audio queue do to exception: "+ e.getMessage(), e);
		}
	}
 
}

首先要清楚的一點是,我們播放歌曲是利用系統內置的MediaPlayer來做的。

1、OnCreate()

我們先看有關初始化的部分。因爲我們要有上一首,下一首的功能,所以首先我們要做的是做一個鏈表,以找到當前播放歌曲的上一首,下一首歌曲的ID值。下面,就是代碼,我利用一個整型數組(private int[] mArrayList = new int[9])來存儲所有歌曲的資源ID;然後利用一個變量mIndex來標識當前播放歌曲的位置。初始化爲4,即默認從中間的歌曲開始放,即R.raw.new_day;

	private void initList() {
		mArrayList[0] = R.raw.dui_ni_ai_bu_wan;
		mArrayList[1] = R.raw.fei_yu;
		mArrayList[2] = R.raw.gu_xiang_de_yun;
		mArrayList[3] = R.raw.hen_ai_hen_ai_ni;
		mArrayList[4] = R.raw.new_day;
		mArrayList[5] = R.raw.shi_jian_li_de_hua;
		mArrayList[6] = R.raw.ye_gui_ren;
		mArrayList[7] = R.raw.yesterday_once_more;
		mArrayList[8] = R.raw.zai_lu_shang;
	}

在OnCreate()函數中,初了始始化部分,我們還應該讓歌曲開始播放,因爲用戶start我們的service的目的就是播放歌曲,所以在OnCreate()中應該初始化MedaiPlayer然後播放默認的的歌曲。即:

	private void mediaPlayerStart(){
		mPlayer = new MediaPlayer();
		mPlayer = MediaPlayer.create(getApplicationContext(), mArrayList[mIndex]);
		mPlayer.start();
	}

2、OnDestroy()

 

在用戶銷燬我們的Service時,應該讓MediaPlayer停止,所以在OnDestroy()中有下面的代碼:

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

3、播放、暫停

 

這兩個功能是最簡單的,直接調用MediaPlayer的函數就能實現,代碼如下 ,不再細講

	public void play(Context context) {
		mPlayer.start();
	}
 
	public void pause(Context context) {
		mPlayer.pause();		
	}

4、上一首、下一首

 

這部分應該是有些難度的,首先,我們要實現根據歌曲資源ID,播放歌曲,代碼如下:

private void playSong(Context context, int resid) {
	
	AssetFileDescriptor afd = context.getResources().openRawResourceFd(mArrayList[mIndex]);
	try {
		mPlayer.reset();
		mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getDeclaredLength());
		mPlayer.prepare();
		mPlayer.start();
		afd.close();
	} catch (Exception e) {
		Log.e("harvic","Unable to play audio queue do to exception: "+ e.getMessage(), e);
	}
}

在mPlayer換歌曲時,先Reset()一下,把MediaPlayer中的資源重置,然後再利用setDataSource()來設置歌曲資源。一定 要注意的是在Start()之前,要調用Prepare()一下。
然後是上一首的實現:

	public void playPrev(Context context) {
		if (--mIndex < 0) {
			mIndex = 8;
		}
		playSong(context, mArrayList[mIndex]);
	}

好了,到這裏,初級的歌曲播放的所有基本功能我們算是實現了。
註冊Service

上面我們就把Service的雛形寫好了,下面要想將Service能啓動起來,就必須在AndroidManifest.xml中註冊,註冊代碼如下:

 <service android:name="com.example.trywidgetsimplest.MusicManageService" ></service>
 <!-- 注意service名稱,必須是從包定位到類名 --> 

一定要注意的是android:name的值一定要從包名開始,一直定位到類名。完整的AndroidManifest.xml代碼如下:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <!-- 聲明widget對應的AppWidgetProvider -->
        <receiver android:name=".ExampleAppWidgetProvider" >
            <intent-filter>
				<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
				<action android:name="com.skywang.widget.UPDATE_ALL"/>
			</intent-filter>
			<meta-data android:name="android.appwidget.provider"
				android:resource="@xml/example_appwidget_info" />
        </receiver>
        
        <service android:name="com.example.trywidgetsimplest.MusicManageService" ></service>
        <!-- 注意service名稱,必須是從包定位到類名 --> 
    </application>

二、MainActivity雛形構建

從最上頭的演示界面也可以看到我們要做的界面是什麼樣子的,下面列出MainAcitivity的佈局代碼(activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#33000000" >
    
    <TextView 
        android:id="@+id/song_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dip"
        android:gravity="center_horizontal"
        android:textSize="14sp"
        android:text="song name"/>
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal" >
 
        <TextView
            android:id="@+id/prev_song"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="8dip"
            android:background="@drawable/car_musiccard_up" />
 
        <TextView
            android:id="@+id/play_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="8dip"
            android:background="@drawable/car_musiccard_play" />
 
        <TextView
            android:id="@+id/next_song"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/car_musiccard_down" />
    </LinearLayout>
 
</FrameLayout>

下面就是控件的響應實現了,實現的邏輯是:當我們第一次點擊播放按鈕時startService(),然後在onDestroy()的時候stopService();完整的代碼如下,然後再細講:

public class MainActivity extends Activity {
	private TextView btn_pre, btn_play_pause, btn_next,songID_tv;
	private int i = 0;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		initCtrls();
	}
	
	private void initCtrls() {
		btn_pre = (TextView) findViewById(R.id.prev_song);
		btn_play_pause = (TextView) findViewById(R.id.play_pause);
		btn_next = (TextView) findViewById(R.id.next_song);
		songID_tv = (TextView)findViewById(R.id.song_name);
 
		btn_pre.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
 
			}
		});
 
		btn_play_pause.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				i++;
				if (i == 1) {
					Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
					startService(startIntent);
				}
 
			}
		});
 
		btn_next.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
 
			}
		});
	}
 
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
		stopService(startIntent);
		super.onDestroy();
	}
 
}

對於初始化控件及按鈕的onClick響應這些東東就沒必要講了,關鍵在於這段代碼:

btn_play_pause.setOnClickListener(new View.OnClickListener() {
 
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		i++;
		if (i == 1) {
			Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
			startService(startIntent);
		}
 
	}
});

我們這裏定義一個變量i,初始化爲0,用戶每次點擊都會加1,但只有用戶第一次點擊時纔會啓動StartService。下面看看stopService的代碼:

@Override
protected void onDestroy() {
	// TODO Auto-generated method stub
	Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
	stopService(startIntent);
	super.onDestroy();
}

在MainActivity銷燬時,利用stopService來停止Service;到這裏,我們MainActivity的基本雛形就完成了,下面就是如何與Service交互的問題了。

三、MainActivity控制MusicManageService播放狀態

從這裏開始就開始涉及MainActivity與MusicManageService交互的內容了,交互分爲兩部分,第一部分就MainActivity的按鈕控制MusicManageService的播放狀態。第二部分是MusicManageService將最新的播放狀態回送給MainActivity讓它更新當前的播放狀態和當前播放歌曲的id值。這裏先講如何通過MainActivity的按鈕控制MusicManageService的播放狀態。

我們與Service通信,一般使用BroadcastReciver,當然也可以使用以前我曾經講過的EventBus,其實使用EventBus是最好的選擇,考慮到很多同學對EventBus不太清楚,這裏選擇使用BroadcastReciver來實現通信。
 

1、MusicManageService中註冊及接收處理消息

首先,我們要在MusicManageService接收MainActivity發送來的消息,所以我們在MusicManageService就要註冊BroadcastReciver(這裏使用動態註冊),然後接收消息並處理,代碼如下:寫貼出完整代碼,然後再細講:

public class MusicManageService extends Service {
 
	private MediaPlayer mPlayer;
	private int mIndex = 4;// 從中間開始放
	private int[] mArrayList = new int[9];
	public static String USR_ACTION = "usr_action_to_service";
	public static String KEY_USR_ACTION = "key_usr_action";
	public static final int ACTION_PRE = 0, ACTION_PLAY_PAUSE = 1, ACTION_NEXT = 2;
	private boolean mPlayState = false;
	
	private BroadcastReceiver receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action  = intent.getAction();
			if (USR_ACTION.equals(action)) {
				int widget_action = intent.getIntExtra(KEY_USR_ACTION, -1);
				
				switch (widget_action) {
				case ACTION_PRE:
					playPrev(context);
					break;
				case ACTION_PLAY_PAUSE:
					if (mPlayState) {
						pause(context);
					}else{
						play(context);
					}	
					break;
				case ACTION_NEXT:
					playNext(context);
					break;
				default:
					break;
				}
			}
			
		}
	};
 
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
 
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(USR_ACTION);
		registerReceiver(receiver, intentFilter);
 
		initList();
		mediaPlayerStart();		
		mPlayState = true;
	}
	
	private void initList() {
		mArrayList[0] = R.raw.dui_ni_ai_bu_wan;
		mArrayList[1] = R.raw.fei_yu;
		mArrayList[2] = R.raw.gu_xiang_de_yun;
		mArrayList[3] = R.raw.hen_ai_hen_ai_ni;
		mArrayList[4] = R.raw.new_day;
		mArrayList[5] = R.raw.shi_jian_li_de_hua;
		mArrayList[6] = R.raw.ye_gui_ren;
		mArrayList[7] = R.raw.yesterday_once_more;
		mArrayList[8] = R.raw.zai_lu_shang;
	}
	
	private void mediaPlayerStart(){
		mPlayer = new MediaPlayer();
		mPlayer = MediaPlayer.create(getApplicationContext(), mArrayList[mIndex]);
		mPlayer.start();
	}
 
	@Override
	public void onDestroy() {
 
		super.onDestroy();
		mPlayer.stop();
	}
 
	/**
	 * 播放下一首
	 * 
	 * @param context
	 */
	public void playNext(Context context) {
		if (++mIndex > 8) {
			mIndex = 0;
		}
		playSong(context, mArrayList[mIndex]);
		mPlayState = true;
	}
 
	/**
	 * 播放上一首
	 * 
	 * @param context
	 */
	public void playPrev(Context context) {
		if (--mIndex < 0) {
			mIndex = 8;
		}
		playSong(context, mArrayList[mIndex]);
		mPlayState = true;
	}
 
	/*
	 * 繼續播放
	 */
	public void play(Context context) {
		mPlayer.start();
		mPlayState = true;
	}
 
	/**
	 * 暫停播放
	 * 
	 * @param context
	 */
	public void pause(Context context) {
		mPlayer.pause();
		mPlayState = false;
	}
 
	/**
	 * 播放指定的歌曲
	 * 
	 * @param context
	 * @param resid
	 */
	private void playSong(Context context, int resid) {
		
		AssetFileDescriptor afd = context.getResources().openRawResourceFd(mArrayList[mIndex]);
		try {
			mPlayer.reset();
			mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getDeclaredLength());
			mPlayer.prepare();
			mPlayer.start();
			afd.close();
		} catch (Exception e) {
			Log.e("harvic","Unable to play audio queue do to exception: "+ e.getMessage(), e);
		}
	}
 
}

首先是定義幾個變量:

public static String USR_ACTION = "usr_action_to_service";
public static String KEY_USR_ACTION = "key_usr_action";
public static final int ACTION_PRE = 0, ACTION_PLAY_PAUSE = 1, ACTION_NEXT = 2;
private boolean mPlayState = false;

USR_ACTION 用來標識發送來的Action;
KEY_USR_ACTION:用來標識發送來的動作的key;
ACTION_PRE = 0, ACTION_PLAY_PAUSE = 1, ACTION_NEXT = 2;是定義的用戶動作,是點的暫停播放按鈕,還是上一首,下一首按鈕。
mPlayState是用來標識當前歌曲是播放狀態還是暫停狀態。因爲我們只有一個按鈕來操作播放暫停,用戶在點擊播放暫停按鈕時發來消息都是ACTION_PLAY_PAUSE,所以我們要標識當前的狀態是播放的還是暫停的,如果是暫停,在收到ACTION_PLAY_PAUSE消息時就播放歌曲,如果是播放,就暫停。

 

然後是接收器:
 

private BroadcastReceiver receiver = new BroadcastReceiver() {
	@Override
	public void onReceive(Context context, Intent intent) {
		String action  = intent.getAction();
		if (USR_ACTION.equals(action)) {
			int widget_action = intent.getIntExtra(KEY_USR_ACTION, -1);
			
			switch (widget_action) {
			case ACTION_PRE:
				playPrev(context);
				break;
			case ACTION_PLAY_PAUSE:
				if (mPlayState) {
					pause(context);
				}else{
					play(context);
				}	
				break;
			case ACTION_NEXT:
				playNext(context);
				break;
			default:
				break;
			}
		}
		
	}
};

這接收器中,先判斷當前發來的action是不是我們所需要的USR_ACTION,如果是就進一步判斷當前的用戶動作,並根據用戶動作調用不同的播放函數如play(),pause()等。

 

最後一步就是註冊接收器,註冊接收器當然是在OnCreate()函數中,即當我們的service被start起來,就開始接收用戶動作消息。這裏還有個問題就是,當我們StartService的時候就已經開始播放歌曲了,所以要在OnCreate()中在mediaPlayerStart()後將mPlayState賦爲true;
 

2、MainActivity中發送消息

發送消息就比較簡單了,就是根據在各個按鈕的onClickListener中根據不同的按鈕點擊發送不同的消息就是了,代碼如下:

public class MainActivity extends Activity {
	private TextView btn_pre, btn_play_pause, btn_next,songID_tv;
	private int i = 0;
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		initCtrls();
	}
	
	private void initCtrls() {
		btn_pre = (TextView) findViewById(R.id.prev_song);
		btn_play_pause = (TextView) findViewById(R.id.play_pause);
		btn_next = (TextView) findViewById(R.id.next_song);
		songID_tv = (TextView)findViewById(R.id.song_name);
 
		btn_pre.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
 
				postAction(MainActivity.this, MusicManageService.ACTION_PRE);
			}
		});
 
		btn_play_pause.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
 
				i++;
				if (i == 1) {
					Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
					startService(startIntent);
				}
				postAction(MainActivity.this,MusicManageService.ACTION_PLAY_PAUSE);
			}
		});
 
		btn_next.setOnClickListener(new View.OnClickListener() {
 
			@Override
			public void onClick(View v) {
				
				postAction(MainActivity.this, MusicManageService.ACTION_NEXT);
			}
		});
	}
	
	private void postAction(Context context, int usr_action) {
		Intent actionIntent = new Intent(MusicManageService.USR_ACTION);
		actionIntent.putExtra(MusicManageService.KEY_USR_ACTION, usr_action);
		context.sendBroadcast(actionIntent);
	}
 
	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		Intent startIntent = new Intent(MainActivity.this,MusicManageService.class);
		stopService(startIntent);
		super.onDestroy();
	}
 
	
}

這部分其實沒什麼好講的,要講的話也就說說這個postAction函數吧:

private void postAction(Context context, int usr_action) {
	Intent actionIntent = new Intent(MusicManageService.USR_ACTION);
	actionIntent.putExtra(MusicManageService.KEY_USR_ACTION, usr_action);
	context.sendBroadcast(actionIntent);
}

首先構建一個intent,然後把用戶當前的操作利用pustExtra傳進去,最後利用context.sendBroadcast(actionIntent);發送出去,無比簡單。就不再講了。

 

到這裏呢,有關控制播放的部分就講完了,下面就是更新MainActivity的界面了,同樣也還是利用BroadcastReceiver,由於多個BroadcastReceiver會讓人搞的有些迷,所以這裏我給出上面的所有代碼的工程。這個工程雖然不能實時更新UI,但已經可以控件歌曲了。
 

四、MusicManageService回送消息更新MainActivity的界面

這部分也是利用BroadcastReceiver,只不過變成了接收方,而MusicManageService成爲了發送方;

1、MainActivity接收消息

 

新代碼如下 ,無外乎也就是註冊接收器,接收消息,處理消息,就不再細講了.難度不大.

public class MainActivity extends Activity {
	private TextView btn_pre, btn_play_pause, btn_next,songID_tv;
	private int i = 0;
	public static String MAIN_ACTIVITY_UPDATE_UI = "main_activity_update_ui";
	public static String KEY_MAIN_ACTIVITY_UI_BTN = "main_activity_ui_btn_key";
	public static String KEY_MAIN_ACTIVITY_UI_TEXT = "main_activity_ui_text_key";
	public static final int  VAL_UPDATE_UI_PLAY = 1,VAL_UPDATE_UI_PAUSE =2;
	
	BroadcastReceiver receiver = new BroadcastReceiver(){
		public void onReceive(Context context, Intent intent) {
			if (intent == null) {
				return;
			}
			String action = intent.getAction();
			if (MAIN_ACTIVITY_UPDATE_UI.equals(action)) {
				int play_pause =  intent.getIntExtra(KEY_MAIN_ACTIVITY_UI_BTN, -1);
				int text = intent.getIntExtra(KEY_MAIN_ACTIVITY_UI_TEXT, -1);
				switch (play_pause) {
				case VAL_UPDATE_UI_PLAY:
					btn_play_pause.setBackgroundResource(R.drawable.car_musiccard_pause);
					songID_tv.setText("current sond id:"+text);
					Log.d("harvic","received play");
					break;
				case VAL_UPDATE_UI_PAUSE:
					btn_play_pause.setBackgroundResource(R.drawable.car_musiccard_play);
					songID_tv.setText("current sond id:" + text);
					Log.d("harvic","received pause");
					break;
 
				default:
					break;
				}
				
			}
		}
	};
 
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(MAIN_ACTIVITY_UPDATE_UI);
		registerReceiver(receiver, intentFilter);
 
		initCtrls();
	}
	……………………//其它代碼一樣,就不再列出	

2、MusicManageService發送消息

這塊就是在播放歌曲,暫停歌曲,上一首,下一首時都要發消息給MainActivity,讓它更新UI

public class MusicManageService extends Service {
 
	private MediaPlayer mPlayer;
	private int mIndex = 4;// 從中間開始放
	private int[] mArrayList = new int[9];
	public static String USR_ACTION = "usr_action_to_service";
	public static String KEY_USR_ACTION = "key_usr_action";
	public static final int ACTION_PRE = 0, ACTION_PLAY_PAUSE = 1, ACTION_NEXT = 2;
	private boolean mPlayState = false;
	
	private BroadcastReceiver receiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action  = intent.getAction();
			if (USR_ACTION.equals(action)) {
				int widget_action = intent.getIntExtra(KEY_USR_ACTION, -1);
				
				switch (widget_action) {
				case ACTION_PRE:
					playPrev(context);
					break;
				case ACTION_PLAY_PAUSE:
					if (mPlayState) {
						pause(context);
					}else{
						play(context);
					}	
					break;
				case ACTION_NEXT:
					playNext(context);
					break;
				default:
					break;
				}
			}
			
		}
	};
 
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return null;
	}
 
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(USR_ACTION);
		registerReceiver(receiver, intentFilter);
 
		initList();
		mediaPlayerStart();		
		mPlayState = true;
	}
	
	private void initList() {
		mArrayList[0] = R.raw.dui_ni_ai_bu_wan;
		mArrayList[1] = R.raw.fei_yu;
		mArrayList[2] = R.raw.gu_xiang_de_yun;
		mArrayList[3] = R.raw.hen_ai_hen_ai_ni;
		mArrayList[4] = R.raw.new_day;
		mArrayList[5] = R.raw.shi_jian_li_de_hua;
		mArrayList[6] = R.raw.ye_gui_ren;
		mArrayList[7] = R.raw.yesterday_once_more;
		mArrayList[8] = R.raw.zai_lu_shang;
	}
	
	private void mediaPlayerStart(){
		mPlayer = new MediaPlayer();
		mPlayer = MediaPlayer.create(getApplicationContext(), mArrayList[mIndex]);
		mPlayer.start();
		postState(getApplicationContext(), MainActivity.VAL_UPDATE_UI_PLAY,mIndex);
	}
 
	@Override
	public void onDestroy() {
 
		super.onDestroy();
		mPlayer.stop();
	}
 
	/**
	 * 播放下一首
	 * 
	 * @param context
	 */
	public void playNext(Context context) {
		if (++mIndex > 8) {
			mIndex = 0;
		}
		playSong(context, mArrayList[mIndex]);
		mPlayState = true;
		postState(context, MainActivity.VAL_UPDATE_UI_PLAY,mIndex);
	}
 
	/**
	 * 播放上一首
	 * 
	 * @param context
	 */
	public void playPrev(Context context) {
		if (--mIndex < 0) {
			mIndex = 8;
		}
		playSong(context, mArrayList[mIndex]);
		mPlayState = true;
		postState(context, MainActivity.VAL_UPDATE_UI_PLAY,mIndex);
	}
 
	/*
	 * 繼續播放
	 */
	public void play(Context context) {
		mPlayer.start();
		mPlayState = true;
		postState(context, MainActivity.VAL_UPDATE_UI_PLAY,mIndex);
	}
 
	/**
	 * 暫停播放
	 * 
	 * @param context
	 */
	public void pause(Context context) {
		mPlayer.pause();
		mPlayState = false;
		postState(context, MainActivity.VAL_UPDATE_UI_PAUSE,mIndex);
	}
 
	/**
	 * 播放指定的歌曲
	 * 
	 * @param context
	 * @param resid
	 */
	private void playSong(Context context, int resid) {
		
		AssetFileDescriptor afd = context.getResources().openRawResourceFd(mArrayList[mIndex]);
		try {
			mPlayer.reset();
			mPlayer.setDataSource(afd.getFileDescriptor(),afd.getStartOffset(), afd.getDeclaredLength());
			mPlayer.prepare();
			mPlayer.start();
			afd.close();
		} catch (Exception e) {
			Log.e("harvic","Unable to play audio queue do to exception: "+ e.getMessage(), e);
		}
	}
	
	private void postState(Context context, int state,int songid) {
		Intent actionIntent = new Intent(MainActivity.MAIN_ACTIVITY_UPDATE_UI);
		actionIntent.putExtra(MainActivity.KEY_MAIN_ACTIVITY_UI_BTN,state);
		actionIntent.putExtra(MainActivity.KEY_MAIN_ACTIVITY_UI_TEXT, songid);
		context.sendBroadcast(actionIntent);
	}
 
}

新增的就是PostState ()函數來發送消息,然後在不同的位置調用而已,難度不大,就不再講了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章