课堂笔记3

制作简单的音乐播放器

    使用service后台播放音乐,制作widget和Activity播放界面,通过BroadcastReceiver进行数据传输

1.Widget

首先创建appwidget-provider布局文件,minWidth和minHeight为widget的最小宽高,系统会根据此宽高自动调节widget在主屏中的大小

previewImage是选择widget时的预览图,如果没有设置会默认为应用图标

initialLayout 初始化weidget,appwidget-provider只是一个布局里面的具体内容由这里提供

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:minHeight="60dp"
    android:previewImage="@drawable/ic_notification"
    android:initialLayout="@layout/widget_layout">

</appwidget-provider>
新建WidgetBroadcast继承于AppWidgetProvider在manifests文件中注册,设置intent-filter,在meta-data中添加android.appwidget.provider以及上面建立的widget布局文件

<receiver android:name=".WidgetBroadcast">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
        <action android:name="com.example.music_service.MUSIC_DATA"/>
        <action android:name="com.example.music_widget.PLAY_ANY"/>
    </intent-filter>
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@layout/widget"
        />
</receiver>
现在widget已经有了接下来设置点击事件

在WidgetBroadcast中重写onUpdate,设置RemoteView以及PendingIntent,再使用appWidgetManager更新Widget

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    super.onUpdate(context, appWidgetManager, appWidgetIds);

    Intent intentService=new Intent(context,MusicService.class);
    context.startService(intentService);
    RemoteViews views=new RemoteViews(context.getPackageName(),R.layout.widget_layout);

    views.setOnClickPendingIntent(R.id.music_start,getIntentForRemoteView(context,WIDGET_START));
    views.setOnClickPendingIntent(R.id.music_next,getIntentForRemoteView(context,WIDGET_NEXT));
    views.setOnClickPendingIntent(R.id.music_previous,getIntentForRemoteView(context,WIDGET_PREVIOUS));

    appWidgetManager.updateAppWidget(appWidgetIds,views);

}
WidgetBroadcast继承的AppWidgetProvider是BroadeReceiver的子类,当Widget点击时会调用onReveive并传递intent,在onRecieve里面发生广播开启服务播放音乐

@Override
public void onReceive(Context context, Intent intent) {
   // boolean state=false;
    super.onReceive(context, intent);

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

    //收到widget始或停点事件后广servicestatefalse为暂停反之为开    if(TextUtils.equals(intent.getAction(),WIDGET_START)){
        if(!state) {
            context.sendBroadcast(getIntentForService(MusicService.SERVICE_PLAY,state));
            remoteViews.setImageViewResource(R.id.music_start,R.drawable.ic_pause_white_24dp);
            Log.d(TAG,"start");
            state=true;
        }else{
            Log.d(TAG,"pause");
            context.sendBroadcast(getIntentForService(MusicService.SERVICE_PLAY,state));
            remoteViews.setImageViewResource(R.id.music_start,R.drawable.ic_play_arrow_white_24dp);
            state=false;
        }
    }
2.Service

在service内新建BroadcastReciver当接受到广播时使用MediaPlayer播放音乐

public  BroadcastReceiver receiver=new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent!=null) {
            if (TextUtils.equals(intent.getAction(), SERVICE_PLAY)) {
                if(!intent.getBooleanExtra("state",true))
                {
                    Log.d(TAG,"play");
                    mMusic.mMusicPlayer.start();
                    MusicService.this.sendBroadcast(mMusic.getMusicIntent());
                }
                else if( mMusic.mMusicPlayer.isPlaying()){
                    mMusic.mMusicPlayer.pause();
                }
            }
在onStartCommand中注册BroadcastReciver

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG,"onStartCommand");
    IntentFilter filter=new IntentFilter();
    filter.addAction(SERVICE_NEXT);
    filter.addAction(SERVICE_PREViOUS);
    filter.addAction(SERVICE_PLAY);
    filter.addAction(MainActivity.PLAY_ANY);
    registerReceiver(receiver,filter);
    return super.onStartCommand(intent, flags, startId);
}
在onDisdroy中unregisterReceiver

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(receiver);
    mMusic.mMusicPlayer.stop();
}

3.音乐文件的读取

新建一个Music类,在构造器中读取assets中music文件夹下的音乐文件名

Music( Context context){
    //得到音文件名数组
    am=context.getAssets();
    try {
        musicFileName=am.list("music");
        Log.d(TAG, Arrays.toString(musicFileName));
        currentPlaying=musicFileName[0];
        mMusicPlayer=new MediaPlayer();
    } catch (IOException e) {
        e.printStackTrace();
        Toast.makeText(context,"到音文件",Toast.LENGTH_SHORT).show();
    }
}
在prepare方法中设置MediaPlayer通过setDataSource读取音乐文件

public void prepare(int fileName){

     if(mMusicPlayer.isPlaying()){
        mMusicPlayer.stop();
    }
    mMusicPlayer.reset();
    Log.d(TAG, "media player reset");
    try {
        mMusicPlayer.setDataSource(getFileDescriptor(),getAssetFD().getStartOffset(),
               getAssetFD().getLength());
        Log.d(TAG, "setDataSource");
        mMusicPlayer.prepare();
        Log.d(TAG, "media prepare");
    } catch (IOException e) {
        e.printStackTrace();
    }
}
开始方法

public void start(){
    mMusicPlayer.start();
}

Activity中的的设置也类似通过广播来传递消息,主要在于和Widget保持同步这里不在赘述

下面是运行结果



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值