您的位置:首页 > 移动开发

Android桌面小部件AppWidget:音乐播放器桌面控制部件Widget(3)

2018-01-04 00:00 639 查看


Android桌面小部件AppWidget:音乐播放器桌面控制部件Widget(3)

Android桌面小部件AppWidget比较常用的场景就是音乐播放器,音乐播放器虽然通常在后台播放,但需要在桌面提供一个可以控制播放状态的APP widget,为用户提供播放、暂停、停止音乐播放器的功能。
在附录文章1、2的基础上,本文以一个简单的例子加以说明,如何通过桌面小部件实现音乐播放器的播放、停止。简单期间,本例只提供对音乐播放器的两种控制功能:播放和停止。播放,进入后台service播放给定的音乐mp3文件;停止,则直接stopService关闭播放服务即可。
为此,需要在桌面的小部件布局中增加两个按钮,这两个按钮暂时就以Android系统默认的播放(@android :drawable/ic_media_play)和暂停(@android :drawable/ic_media_pause)图片作为按钮使用。当按了播放按钮后,就开始启动后台服务播放mp3音乐文件(暂时以我放置在SDCard根目录下名为zhangphil.mp3的音乐文件为音频源文件);当按了停止按钮后,就stopService,即停止播放。
和附录文章1,2相比,本例不需要更新桌面小部件的表现形式,仅需要处理由桌面小部件传导过来的点击事件,这些响应点击事件,均放置在onReceive里面处理。

(1)

在Androidmanifest.xml里面定义的widget:

<receiver android:name="zhangphil.widget.AppWidget" >

<intent-filter>
<action android:name="action_play" />
</intent-filter>

<intent-filter>
<action android:name="action_stop" />
</intent-filter>

<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>

<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget" />

</receiver>


涉及到res/xml目录下的appwidget.xml代码文件:

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/appwidget_layout"
android:minHeight="20dip"
android:minWidth="300dip"
android:previewImage="@drawable/ic_launcher"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen" >

</appwidget-provider>


(2)service播放音乐。也在Androidmanifest.xml里面定义:

<service android:name="zhangphil.widget.MyService" >
</service>


(3)核心关键的AppWidget.java代码文件:

package zhangphil.widget;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;

public class AppWidget extends AppWidgetProvider {

@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
// Log.d(this.getClass().getName(), "onReceive");

if (intent == null)
return;

String action = intent.getAction();

// 停止播放
if (action.equals(Constants.ACTION_STOP)) {
Intent serviceIntent = new Intent(context, MyService.class);
context.stopService(serviceIntent);
}

// 点击了按钮,启动一个后台服务播放
if (action.equals(Constants.ACTION_PLAY)) {
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
}
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(this.getClass().getName(), "onUpdate");

RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);

// 播放图片作为按钮,绑定播放事件
Intent intentPlay = new Intent(Constants.ACTION_PLAY);
PendingIntent pendingIntentPlay = PendingIntent.getBroadcast(context, Constants.REQUEST_CODE_PLAY, intentPlay,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.play, pendingIntentPlay);

// 停止图片作为按钮,绑定停止事件
Intent intentStop = new Intent(Constants.ACTION_STOP);
PendingIntent pendingIntentStop = PendingIntent.getBroadcast(context, Constants.REQUEST_CODE_STOP, intentStop,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.stop, pendingIntentStop);

// 更新AppWidget
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}

/**
* 删除AppWidget
*/
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
super.onDeleted(context, appWidgetIds);
Log.d(this.getClass().getName(), "onDeleted");
}

@Override
public void onDisabled(Context context) {
super.onDisabled(context);
Log.d(this.getClass().getName(), "onDisabled");
}

/**
* AppWidget首次创建调用
*/
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
Log.d(this.getClass().getName(), "onEnabled");
}
}


AppWidget.java里面RemoteViews用到的布局文件appwidget_layout.xml:

<?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="wrap_content"
android:background="#33000000"
android:orientation="horizontal" >

<ImageView
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_media_play" >
</ImageView>

<ImageView
android:id="@+id/stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_media_pause" >
</ImageView>

</LinearLayout>


(4)service后台服务MyService.java,该部分代码将负责在后台播放或者停止音播放:

package zhangphil.widget;

import java.io.File;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.IBinder;

public class MyService extends Service {

// 播放器
private MediaPlayer mMediaPlayer;

// 音频文件
private File audioFile;

@Override
public void onCreate() {
super.onCreate();

mMediaPlayer = new MediaPlayer();

// 根目录
File sdcard = Environment.getExternalStorageDirectory();
audioFile = new File(sdcard, "zhangphil.mp3");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 重置
mMediaPlayer.reset();

// 设置播放器的声音源
try {
mMediaPlayer.setDataSource(audioFile.getAbsolutePath());
} catch (Exception e) {
e.printStackTrace();
}

// 也可以从一个静态资源文件中加载音频数据源
// mMediaPlayer.create(this, R.raw.xxx);

if (!mMediaPlayer.isPlaying()) {
try {
mMediaPlayer.prepare();
} catch (Exception e) {
e.printStackTrace();
}

mMediaPlayer.start();

// 如果设置循环true,那么将循环播放
// mMediaPlayer.setLooping(true);
}

return super.onStartCommand(intent, flags, startId);
}

@Override
public void onDestroy() {
super.onDestroy();

mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
}

@Override
public IBinder onBind(Intent intent) {
return null;
}
}


(5)定义的公共静态变量Constants.java:

package zhangphil.widget;

public class Constants {
public static final String ACTION_PLAY = "action_play";
public static final String ACTION_STOP = "action_stop";
public static final int REQUEST_CODE_PLAY = 0xd05;
public static final int REQUEST_CODE_STOP = 0xd06;
}


代码运行结果如图所示:



附录文章:
1,《Android桌面小部件AppWidget(1)》链接地址:http://blog.csdn.net/zhangphil/article/details/50457355
2,《Android桌面小部件AppWidget(2)》链接地址:http://blog.csdn.net/zhangphil/article/details/50461944
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: