安卓实训项目:基于储存卡音乐播放器实训报告5.0

(一)功能要求

在基于存储卡音乐播放器V0.4基础上,作如下修改:

1、创建应用程序常量接口保存广播频道常量
2、在音乐播放器应用程序类里添加两个属性
– currentMusicIndex
– currentPosition
– 访问它们的方法
3、创建MusicPlayService来完成音乐的播放、暂停以及切换工作
4、利用广播来实现MainActivity与MusicPlayService之间的通信

(二)运行效果

(三)涉及知识点

1.标签(TextView)
2.按钮(Button)
3.媒体播放器(MediaPlayer)
4.进度条(ProgressBar)
5.线程(Thread)
6.消息处理器(Handler)
7.列表视图(ListView)
8.异步任务(AsyncTask)
9.应用程序(Application)
10.服务(Service)
11.广播接收者(BroadcastReceiver)

(四)实现步骤

1.创建安卓应用【SDCardMusicPlayerV0.5】


2、将图片素材拷贝到drawable目录与mipmap目录

3、播放按钮背景图片选择器 - play_button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/play_button_pressed" android:state_pressed="true"/><item android:drawable="@drawable/play_button" android:state_pressed="false"/>
</selector>

4、暂停按钮背景图片选择器 - pause_button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/pause_button_pressed" android:state_pressed="true" /><item android:drawable="@drawable/pause_button" android:state_pressed="false" />
</selector>

该处使用的url网络请求的数据。


5、上一首按钮背景图片选择器 - previous_button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/previous_button_pressed" android:state_pressed="true" /><item android:drawable="@drawable/previous_button" android:state_pressed="false" />
</selector>

6、下一首按钮背景图片选择器 - next_button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:drawable="@drawable/next_button_pressed" android:state_pressed="true" /><item android:drawable="@drawable/next_button" android:state_pressed="false" />
</selector>

7、文件里授权访问外置存储卡,设置应用程序图标

8、主布局资源文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/background"android:orientation="vertical"android:padding="20dp"tools:context=".ui.MainActivity"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ProgressBarandroid:id="@+id/pbScanMusic"android:layout_width="100dp"android:layout_height="100dp"android:visibility="gone" /><TextViewandroid:id="@+id/tvScanMusic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/scan_music"android:textColor="#0000ff"android:textSize="25sp"android:visibility="gone" /></LinearLayout><ListViewandroid:id="@+id/lvMusicName"android:layout_width="match_parent"android:layout_height="0dp"android:layout_marginBottom="16dp"android:layout_weight="8" /><TextViewandroid:id="@+id/tvMusicName"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="0.5"android:textColor="#0000ff"android:textSize="20sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:layout_marginBottom="10dp"android:layout_weight="0.5"android:gravity="center"android:orientation="horizontal"><TextViewandroid:id="@+id/tvCurrentPosition"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textColor="#ff0000" /><ProgressBarandroid:id="@+id/pbMusicProgress"style="?android:attr/progressBarStyleHorizontal"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="6" /><TextViewandroid:id="@+id/tvDuration"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:textColor="#ff00ff" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="0.5"android:gravity="center"android:orientation="horizontal"><Buttonandroid:id="@+id/btnPrevious"android:layout_width="60dp"android:layout_height="50dp"android:background="@drawable/previous_button_selector"android:onClick="doPrevious" /><Buttonandroid:id="@+id/btnPlayOrPause"android:layout_width="60dp"android:layout_height="50dp"android:background="@drawable/play_button_selector"android:onClick="doPlayOrPause" /><Buttonandroid:id="@+id/btnNext"android:layout_width="60dp"android:layout_height="50dp"android:background="@drawable/next_button_selector"android:onClick="doNext" /></LinearLayout>
</LinearLayout>

9、字符串资源文件strings.xml

<resources><string name="app_name">基于存储卡音乐播放器V0.5</string><string name="scan_music">扫描外置存储卡上全部MP3音乐,请耐心等待……</string>
</resources>

10、创建音乐名列表项模板music_name_list_item.xml

11、创建ui子包,将MainActivity拖进ui子包

12、创建entity子包,在里面创建音乐实体类 - Music

package com.example.musicplayerv05.entity;import androidx.annotation.NonNull;/*** 功能:音乐实体类* 作者:幸亮* 日期:2021年01月05日*/public class Music {private String musicName;//音乐名public String getMusicName(){return musicName;}public void setMusicName(String musicName){this.musicName = musicName;}@NonNull@Overridepublic String toString() {return "Music{" +"musicName'" + musicName + '\'' +'}';}
}

13、创建app子包,在里面创建音乐播放器应用程序类 - MusicPlayerApplication

package com.example.musicplayerv05.app;import android.app.Application;
import android.os.Environment;import com.example.musicplayerv05.entity.Music;import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;public class MusicPlayerApplication extends Application {private SimpleDateFormat sdf; // 简单日期格式private int currentMusicIndex;//当前音乐索引private int currentPosition;//当前播放位置@Overridepublic void onCreate() {super.onCreate();// 实例化简单日期格式sdf = new SimpleDateFormat("mm:ss");}public int getCurrentMusicIndex() {return currentMusicIndex;}public void setCurrentMusicIndex(int currentMusicIndex) {this.currentMusicIndex = currentMusicIndex;}public int getCurrentPosition() {return currentPosition;}public void setCurrentPosition(int currentPosition) {this.currentPosition = currentPosition;}/*** 获取格式化时间** @param time 单位是毫秒* @return mm:ss格式的时间*/public String getFormatTime(int time) {return sdf.format(time);}/*** 生成指定目录下某种类型的文件列表** @param dir* @param suffix* @param typeFileList*/public void makeTypeFileList(File dir, String suffix, List<String> typeFileList) {// 获取指定目录下的File数组(File既可以指向目录,也可以指向文件)File[] files = dir.listFiles();// 遍历File数组for (File file : files) {// 判断file是否是文件if (file.isFile()) { // file是文件// 按照后缀来过滤文件if (file.getName().endsWith(suffix)) {// 将满足条件的文件添加到文件列表typeFileList.add(file.getAbsolutePath());}} else { // file是目录// 目录非空,递归调用if (file.list() != null) {makeTypeFileList(file, suffix, typeFileList);}}}}/*** 获取音乐列表** @return 音乐列表*/public List<Music> getMusicList() {// 声明音乐列表List<Music> musicList = null;// 获取外置存储卡根目录File sdRootDir = Environment.getExternalStorageDirectory();// 创建后缀字符串String suffix = ".mp3";// 创建音乐文件列表List<String> musicFileList = new ArrayList<>();// 调用方法,生成指定目录下某种类型文件列表makeTypeFileList(sdRootDir, suffix, musicFileList);// 判断音乐文件列表里是否有元素if (musicFileList.size() > 0) {// 实例化音乐列表musicList = new ArrayList<>();// 遍历音乐文件列表for (String musicFile : musicFileList) {// 创建音乐实体Music music = new Music();// 设置实体属性music.setMusicName(musicFile);// 将音乐实体添加到音乐列表musicList.add(music);}}// 返回音乐列表return musicList;}
}

14、在项目清单文件里给音乐播放器应用程序类注册

15、创建adapter子包,在里面创建音乐适配器 - MusicAdapter

package com.example.musicplayerv05.adapter;import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;import com.example.musicplayerv05.R;
import com.example.musicplayerv05.entity.Music;import java.util.List;public class MusicAdapter extends BaseAdapter{private Context context; // 上下文private List<Music> musicList; // 音乐列表/*** 构造方法** @param context* @param musicList*/public MusicAdapter(Context context, List<Music> musicList) {this.context = context;this.musicList = musicList;}@Overridepublic int getCount() {return musicList.size();}@Overridepublic Object getItem(int position) {return musicList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// 声明视图容器ViewHolder holder = null;// 判断转换视图是否为空if (convertView == null) {// 将列表项模板映射成转换视图convertView = LayoutInflater.from(context).inflate(R.layout.music_name_list_item, null);// 创建视图容器对象holder = new ViewHolder();// 实例化转换视图里的控件holder.tvMusicName = convertView.findViewById(R.id.tvMusicName);// 将视图容器附加到转换视图convertView.setTag(holder);} else {// 从转换视图里取出视图容器holder = (ViewHolder) convertView.getTag();}// 获取列表项要显示的数据Music music = musicList.get(position);// 设置列表项控件的属性(去掉路径和扩展名)holder.tvMusicName.setText(music.getMusicName().substring(music.getMusicName().lastIndexOf("/") + 1, music.getMusicName().lastIndexOf(".")));// 返回转换视图return convertView;}/*** 视图容器*/private static class ViewHolder {TextView tvMusicName;}
}

16、在app子包常见应用程序常量接口 - AppConstants

package com.example.musicplayerv05.app;public interface AppConstants {String TAG = "com.example.musicplayerv05"; // 应用程序标记String INTENT_ACTION_PREVIOUS = TAG + ".intent.action.PREVIOUS"; // 广播频道常量:播放上一首String INTENT_ACTION_PLAY = TAG + ".intent.action.PLAY"; // 广播频道常量:播放String INTENT_ACTION_PLAY_OR_PAUSE = TAG + ".intent.action.PLAY_OR_PAUSE"; // 广播频道常量:播放或暂停String INTENT_ACTION_NEXT = TAG + ".intent.action.NEXT"; // 广播频道常量:播放下一首String INTENT_ACTION_UPDATE_PROGRESS = TAG + ".intent.action.UPDATE_PROGRESS"; // 广播频道常量:更新播放进度String CONTROL_ICON = "control_icon"; // 控制图标名称常量String DURATION = "duration"; // 播放时长名称常量String CURRENT_POSITION = "current_position"; // 当前播放位置名称常量
}

17、创建service子包,在里面创建音乐播放服务类 - MusicPlayService

package com.example.musicplayerv05.Service;import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.os.IBinder;import androidx.annotation.Nullable;import com.example.musicplayerv05.R;
import com.example.musicplayerv05.app.AppConstants;
import com.example.musicplayerv05.app.MusicPlayerApplication;
import com.example.musicplayerv05.entity.Music;import java.io.IOException;
import java.util.List;public class MusicPlayService extends Service implements AppConstants {private MediaPlayer mp; // 媒体播放器private String musicName; // 音乐文件名private Thread thread; // 线程private boolean isRunning; // 线程循环控制变量private List<Music> musicList;//音乐数据源private MusicPlayerApplication app;//音乐播放器应用程序private MusicReceiver receiver;//广播接收者@Overridepublic void onCreate() {super.onCreate();//获取音乐播放器对象app = (MusicPlayerApplication) getApplication();//获取音乐列表musicList = app.getMusicList();//创建媒体播放器mp = new MediaPlayer();//给媒体播放器注册完成监听器mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mediaPlayer) {//切换下一曲nextMusic();}});//设置循环变量为真isRunning = true;//创建子线程,定时发送消息thread = new Thread(() -> {while (isRunning) {if (mp.isPlaying()) {//创建意图Intent intent = new Intent();//设置广播频道intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);//设置当前播放位置app.setCurrentPosition(mp.getCurrentPosition());//让意图携带播放时长数据intent.putExtra(DURATION, mp.getDuration());//暂停图标intent.putExtra(CONTROL_ICON, R.drawable.pause_button_selector);//发送广播sendBroadcast(intent);try {//线程休眠500毫秒Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}});//启动更新进度的线程thread.start();//创建音乐广播接收器receiver = new MusicReceiver();//创建意图过滤器IntentFilter filter = new IntentFilter();//通过意图过滤器添加广播频道filter.addAction(INTENT_ACTION_PLAY_OR_PAUSE);filter.addAction(INTENT_ACTION_PLAY);filter.addAction(INTENT_ACTION_PREVIOUS);filter.addAction(INTENT_ACTION_NEXT);//注册广播接收者registerReceiver(receiver, filter);}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {//获取播放音乐名musicName = musicList.get(app.getCurrentMusicIndex()).getMusicName();try {//设置播放源mp.setDataSource(musicName);//缓冲播放源mp.prepare();//播放位置归零app.setCurrentPosition(0);//创建意图Intent intent1 = new Intent();//更新进度intent1.setAction(INTENT_ACTION_UPDATE_PROGRESS);//让意图携带播放时长intent1.putExtra(DURATION, mp.getDuration());//发送广播sendBroadcast(intent1);} catch (IOException e) {e.printStackTrace();}//返回非粘性服务return Service.START_NOT_STICKY;}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}/*** 销毁回调方法*/@Overridepublic void onDestroy() {super.onDestroy();// 释放播放器if (mp != null) {mp.release();mp = null;}//注销广播接收者unregisterReceiver(receiver);//设置线程循环控制变量isRunning = false;//销毁子线程thread = null;}/*** 播放方法*/private void play() {try {// 重置媒体播放器mp.reset();//获取当前播放的音乐名musicName = musicList.get(app.getCurrentMusicIndex()).getMusicName();// 设置播放源(完整音乐名 = 音乐目录 + 音乐名)mp.setDataSource(musicName);// 缓冲播放源(从存储卡加载到内存)mp.prepare();// 定位到暂停时的播放位置mp.seekTo(app.getCurrentPosition());// 启动音乐的播放mp.start();} catch (IOException e) {e.printStackTrace();}}/*** 上一曲*/private void previousMusic() {//更新索引if (app.getCurrentMusicIndex() > 0) {app.setCurrentMusicIndex(app.getCurrentMusicIndex() - 1);} else {app.setCurrentMusicIndex(musicList.size() - 1);}//位置归零app.setCurrentPosition(0);//调用播放方法play();}/*** 下一曲*/private void nextMusic() {//更新索引if (app.getCurrentMusicIndex() < musicList.size() - 1) {app.setCurrentMusicIndex(app.getCurrentMusicIndex() + 1);} else {app.setCurrentMusicIndex(0);}//播放位置归零app.setCurrentPosition(0);play();}/*** 暂停方法*/private void pause() {// 暂停播放mp.pause();// 保存音乐播放的当前位置app.setCurrentPosition(mp.getCurrentPosition());// 创建意图Intent intent = new Intent();//设置广播频道更新进度intent.setAction(INTENT_ACTION_UPDATE_PROGRESS);//携带播放时长数据intent.putExtra(DURATION, mp.getDuration());//控制图标intent.putExtra(CONTROL_ICON, R.drawable.play_button_selector);//发送广播sendBroadcast(intent);}/*** 音乐广播接收者*/private class MusicReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//获取意图动作(广播频道)String action = intent.getAction();//对广播频道非空判断if (action != null) {switch (action) {case INTENT_ACTION_PLAY://单击列表项//进度归零app.setCurrentPosition(0);//播放play();break;case INTENT_ACTION_PLAY_OR_PAUSE://单击播放|暂停按钮//判断是否播放if (mp.isPlaying()) {pause();} else {play();}break;case INTENT_ACTION_PREVIOUS://上一曲//上一曲previousMusic();break;case INTENT_ACTION_NEXT://下一曲//切换下一曲nextMusic();break;}}}}
}

18、在项目清单文件里注册音乐播放服务

19、主界面类 - MainActivity

package com.example.musicplayerv05.ui;import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;import com.example.musicplayerv05.R;
import com.example.musicplayerv05.Service.MusicPlayService;
import com.example.musicplayerv05.adapter.MusicAdapter;
import com.example.musicplayerv05.app.AppConstants;
import com.example.musicplayerv05.app.MusicPlayerApplication;
import com.example.musicplayerv05.entity.Music;import java.util.List;public class MainActivity extends AppCompatActivity implements AppConstants {private String musicName; // 音乐文件名private TextView tvMusicName; // 音乐名标签private Button btnPlayOrPause; // 播放|暂停按钮private MusicReceiver receiver;//广播接收器private TextView tvCurrentPosition; // 显示当前播放位置的标签private TextView tvDuration; // 显示音乐播放时长的标签private ProgressBar pbMusicProgress; // 音乐播放进度条private List<Music> musicList;//音乐数据源private ListView lvMusicName;//音乐名控件列表private MusicAdapter adapter;//适配器private MusicPlayerApplication app;//音乐播放器应用程序private ProgressBar pbScanMusic;//扫描存储卡进度条private TextView tvScanMusic;//扫描存储卡音乐标签@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//获取实例lvMusicName = findViewById(R.id.lvMusicName);btnPlayOrPause = findViewById(R.id.btnPlayOrPause);tvMusicName = findViewById(R.id.tvMusicName);tvCurrentPosition = findViewById(R.id.tvCurrentPosition);tvDuration = findViewById(R.id.tvDuration);pbMusicProgress = findViewById(R.id.pbMusicProgress);pbScanMusic = findViewById(R.id.pbScanMusic);tvScanMusic = findViewById(R.id.tvScanMusic);//获取音乐播放器应用程序对象app = (MusicPlayerApplication) getApplication();// 定义存储读写权限数组String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE};// 检查是否有读权限int permission = ActivityCompat.checkSelfPermission(this, PERMISSIONS_STORAGE[0]);// 如果没有授权,那么就请求读权限if (permission != PackageManager.PERMISSION_GRANTED) {ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, 0);return;}//启动填充音乐播放列表异步任务new FillMusicListTask().execute();lvMusicName.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {//获取音乐索引app.setCurrentMusicIndex(position);//播放进度归零app.setCurrentPosition(0);//获取音乐名musicName = app.getMusicList().get(position).getMusicName();//设置音乐名,去掉路径和扩展名tvMusicName.setText("No." + (app.getCurrentMusicIndex() + 1) + " " + musicName.substring(musicName.lastIndexOf("/") + 1, musicName.lastIndexOf(".")));//创建意图Intent intent = new Intent();//设置广播频道:播放intent.setAction(INTENT_ACTION_PLAY);//发送广播sendBroadcast(intent);}});//创建音乐广播接收器receiver = new MusicReceiver();//创建过滤器IntentFilter filter = new IntentFilter();//通过过滤器添加广播频道filter.addAction(INTENT_ACTION_UPDATE_PROGRESS);//注册广播接收器registerReceiver(receiver,filter);}/*** 音乐广播接收器*/private class MusicReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//获取广播频道String action = intent.getAction();//判断广播频道是否为空if (action != null){//根据不同广播频道执行不同操作if (INTENT_ACTION_UPDATE_PROGRESS.equals(action)){//获取播放时长int duration = intent.getIntExtra(DURATION,0);//获取播放图标int controlIcon = intent.getIntExtra(CONTROL_ICON,R.drawable.play_button_selector);//计算进度int progress = app.getCurrentPosition() * 100 / duration;//获取音乐名musicName = app.getMusicList().get(app.getCurrentMusicIndex()).getMusicName();//设置音乐名,去掉多余部分tvMusicName.setText("No."+(app.getCurrentMusicIndex()+1)+" "+ musicName.substring(musicName.lastIndexOf("/")+1,musicName.lastIndexOf(".")));//设置进度标签tvCurrentPosition.setText(app.getFormatTime(app.getCurrentPosition()));//设置时长标签tvDuration.setText(app.getFormatTime(duration));//设置进度条pbMusicProgress.setProgress(progress);//设置按钮图标btnPlayOrPause.setBackgroundResource(controlIcon);}}}}/*** 填充音乐列表异步任务类*/private class FillMusicListTask extends AsyncTask<Void, Integer, Void> {/*** 耗时工作执行前*/@Overrideprotected void onPreExecute() {super.onPreExecute();//设置进度条属性pbScanMusic.setVisibility(View.VISIBLE);//设置文字属性tvScanMusic.setVisibility(View.VISIBLE);}protected Void doInBackground(Void... voids) {musicList = app.getMusicList();for (long i = 0; i < 2000000000; i++) {}return null;}/*** 耗时工作后* @param aVoid*/@Overrideprotected void onPostExecute(Void aVoid) {super.onPostExecute(aVoid);pbScanMusic.setVisibility(View.GONE);tvScanMusic.setVisibility(View.GONE);//判断列表是否为空if (musicList.size() > 0) {//创建适配器adapter = new MusicAdapter(MainActivity.this, musicList);//设置适配器lvMusicName.setAdapter(adapter);//获取音乐名标签内容(默认为第一首)musicName = musicList.get(0).getMusicName();//设置播放音乐名tvMusicName.setText("No." + (app.getCurrentMusicIndex() + 1) + " " + musicName.substring(musicName.lastIndexOf("/") + 1, musicName.lastIndexOf(".")));Intent intent = new Intent(MainActivity.this, MusicPlayService.class);startService(intent);} else {Toast.makeText(MainActivity.this, "存储卡Music目录里没有音乐文件!", Toast.LENGTH_SHORT).show();}}}/***上一曲* @param view*/public void doPrevious(View view){//创建意图Intent intent = new Intent();//设置广播频道intent.setAction(INTENT_ACTION_PREVIOUS);//发送广播sendBroadcast(intent);}/***下一曲* @param view*/public void doNext(View view){//创建意图Intent intent = new Intent();//设置广播频道intent.setAction(INTENT_ACTION_NEXT);//发送广播sendBroadcast(intent);}/*** 播放暂停* @param view*/public void doPlayOrPause(View view){//创建意图Intent intent = new Intent();//设置广播频道intent.setAction(INTENT_ACTION_PLAY_OR_PAUSE);//发送广播sendBroadcast(intent);}/*** 销毁回调方法*/@Overrideprotected  void onDestroy(){super.onDestroy();//停止音乐播放服务stopService(new Intent(MainActivity.this, MusicPlayService.class));//注销广播接收器if (receiver != null){unregisterReceiver(receiver);}}
}

安卓实训项目:基于储存卡音乐播放器实训报告5.0相关推荐

  1. 安卓实训项目:基于储存卡音乐播放器实训报告4.0

    功能要求 在基于存储卡音乐播放器V0.3基础上,作如下修改: 1.创建方法能扫描存储卡上所有mp3文件(采用递归算法) ----完成 2.用自定义应用程序类存放全局数据和方法 ----完成 3.利用异 ...

  2. 安卓第一阶段实训项目:基于存储卡音乐播放器(更新中……)

    文章目录 一.项目功能要求 二.涉及知识点 三.实现思路 1.基于存储卡音乐播放器V0.1 2.基于存储卡音乐播放器V0.2 3.基于存储卡音乐播放器V0.3 4.基于存储卡音乐播放器V0.4 5.基 ...

  3. 基于android音乐播放器的设计

    本科毕业论文(设计)诚信声明 本人郑重声明:所呈交的毕业论文(设计),题目<---基于android音乐播放器的设计----------->是本人在指导教师的指导下,进行研究工作所取得的成 ...

  4. android音乐播放器ppt,基于Android音乐播放器设计与开发.ppt

    基于Android音乐播放器设计与开发 毕业设计 基于Android的音乐播放器 设计与开发 设计概述 研究背景 研究意义 研究目标 系统演示 研究背景 随着Android智能手机的普及,用户越来越能 ...

  5. 基于android的音乐播放器毕业设计,基于android音乐播放器的毕业设计ppt

    <基于android音乐播放器的毕业设计ppt>由会员分享,可在线阅读,更多相关<基于android音乐播放器的毕业设计ppt(29页珍藏版)>请在人人文库网上搜索. 1.1. ...

  6. 基于android音频感知系统,本科毕业论文—基于android音乐播放器的设计与实现专科.doc...

    本科毕业论文-基于android音乐播放器的设计与实现专科.doc 专科毕业设计(论文) 题 目 基于Android的音乐播放器设计与实现 毕业论文(设计)原创性声明 本人所呈交的毕业论文(设计)是我 ...

  7. 简单android音乐播放器课程设计,android音乐播放器课程设计报告.doc

    android音乐播放器课程设计报告 android音乐播放器课程设计报告 基于Android音乐播放器的设计与实现 滨江学院 <移动通信程序设计> 课程设计 题 目 院 系 专 业学生姓 ...

  8. android音乐播放器课程设计报告,android音乐播放器课程设计报告11.doc

    最新精品文档,知识共享! android音乐播放器课程设计报告 基于Android音乐播放器的设计与实现 滨江学院 <移动通信程序设计> 课程设计 题 目 院 系 专 业学生姓名 学 号 ...

  9. android音乐播放器实验报告总结,音乐播放器设计实验报告.docx

    音乐播放器设计实验报告.docx 实验报告课程名称数字系统设计实验指导老师成绩_____________实验名称音乐播放器设计实验实验类型设计型一.实验目的和要求(必填)二.实验内容和原理(必填)三. ...

最新文章

  1. 如何利用扬声器构建深度学习网络?
  2. 利用Tencent(腾讯)SCF函数部署自动签到获得容量(天翼云盘)
  3. DOM中的setInterval方法
  4. jvm性能调优实战 -51修复栈内存区域内存溢出问题 StackOverFlow
  5. ui设计和python哪个容易学_软件开发和ui设计那个容易学?
  6. node.js mysql 不退出,mysql - 错误:使用NodeJS在MySQL中调用退出后无法排队查询 - SO中文参考 - www.soinside.com...
  7. 以太坊钱包开发系列3 - 展示钱包信息及发起签名交易
  8. ofstream与ate的故事 经典!
  9. 联想超融合平台oracle,联想AIO超融合云一体机解决方案.pdf
  10. github java开源项目经验_Java 开源项目 GitHub 趋势周报 20201230
  11. python怎么导入txt文件-python – 如何一次读取和附加到文本文件?
  12. 私有属性的另类访问方式
  13. 计算机英语词汇合成词有哪些,2018年12月英语四级词汇讲解丨考点归纳:合成词...
  14. 视频拍摄——视点和视角
  15. 六轴机器人光机_烂大街的六轴机器人
  16. 网络协议分为哪几层---物理层,连接层,网络层,传输层,应用层详解
  17. android 定时响铃,Android开发振动和响铃
  18. 远控杂说---总有一款适合你
  19. html哭脸字符,科学网—Unicode中的符号 - 丁祥欢的博文
  20. 【UCIe】UCIe 协议层介绍

热门文章

  1. Sublime Text 3在ubuntu12.10下无法中文输入的解决方案
  2. 成功人士,默默做的30件事 (4-6)
  3. 用JSP实现上传文件的两种方法
  4. java模拟退火程序
  5. java 反射 Gc_深入浅析Java反射机制
  6. 英伟达驱动更新记录_N卡驱动更新软件(NVIDIA GeForce Experience) v3.16.0.122 官方版
  7. 【Paper】23_[14]A Decentralized Approach to Formation Maneuvers
  8. 2.18 Logistic 损失函数的解释-深度学习-Stanford吴恩达教授
  9. Ardino基础教程 13_温度传感器
  10. linux中的查找文件夹