读取手机联系人
package com.example.mp;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义工具类
* 查询本地歌曲
*/
public class ReadMyMusic {
public static List<MyMusic> read(Context con){
List<MyMusic> list=new ArrayList<>();
Uri uri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
ContentResolver cr = con.getContentResolver();
Cursor query = cr.query(uri, null, null, null, null);
if( query!=null){
// Toast.makeText(con, "没有读取到数据。", Toast.LENGTH_SHORT).show();
// return null;
// }else{
int index=0;
while (query.moveToNext()) {
String title = query.getString(query.getColumnIndex(MediaStore.Audio.Media.TITLE));
Toast.makeText(con, "title" + title, Toast.LENGTH_SHORT).show();
String artist = query.getString(query.getColumnIndex(MediaStore.Audio.Media.ARTIST));
String duration = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DURATION));
String size = query.getString(query.getColumnIndex(MediaStore.Audio.Media.SIZE));
String data = query.getString(query.getColumnIndex(MediaStore.Audio.Media.DATA));
MyMusic mm = new MyMusic();
mm.setSize(Integer.parseInt(size));
mm.setTitle(title);
mm.setArtist(artist);
mm.setData(data);
mm.setPosition(index);
mm.setDuration(duration);
index++;
list.add(mm);
Toast.makeText(con, mm.toString(), Toast.LENGTH_SHORT).show();
}
Toast.makeText(con, "读取完毕。"+list.size(), Toast.LENGTH_SHORT).show();
query.close();
}
return list;
}
}
自定义Music类存储读取到的手机联系人
package com.example.mp;
public class MyMusic {
//作曲家
private String Artist;
private String title;
private String data;
private long size;
private int position;
private String duration;
@Override
public String toString() {
return "MyMusic{" +
"Artist='" + Artist + '\'' +
", title='" + title + '\'' +
", data='" + data + '\'' +
", size=" + size +
", position=" + position +
", duration='" + duration + '\'' +
'}';
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getArtist() {
return Artist;
}
public void setArtist(String artist) {
Artist = artist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
}
自定义适配器
向GridView添加数据
package com.example.mp;
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 java.util.List;
public class MyAdapter extends BaseAdapter {
private Context con;
private List<MyMusic> list;
private MyId mi;
public MyAdapter(Context con, List<MyMusic> list) {
this.con = con;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if( convertView==null){
convertView= LayoutInflater.from(con).inflate(R.layout.mylayout,null);
mi=new MyId();
mi.artist=convertView.findViewById(R.id.layout_artist);
mi.title=convertView.findViewById(R.id.layout_title);
mi.data=convertView.findViewById(R.id.layout_data);
mi.size=convertView.findViewById(R.id.layout_tsize);
mi.position=convertView.findViewById(R.id.layout_position);
mi.duration=convertView.findViewById(R.id.layout_duration);
convertView.setTag(mi);
}else{
mi= (MyId) convertView.getTag();
}
mi.duration.setText(list.get(position).getDuration());
mi.artist.setText(list.get(position).getArtist());
mi.title.setText(list.get(position).getTitle());
// mi.position.setText(list.get(position).getPosition());
mi.data.setText(list.get(position).getData());
mi.size.setText(list.get(position).getSize()+"");
return convertView;
}
class MyId{
private TextView artist;
private TextView title;
private TextView data;
private TextView size;
private TextView position;
private TextView duration;
}
}
主界面
package com.example.mp;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.SeekBar;
import com.example.mp.MyBroadCast.MyReceiver;
import com.example.mp.MyService.MyService;
import java.sql.Time;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
private List<MyMusic> read=new ArrayList<>();
private GridView gridView;
public static MyService.MyBinder binder;
private static int index;
private int radomIndex=-1;
private int along=-1;
private SeekBar sb;
private Button but;
@SuppressLint("HandlerLeak")
public static Handler han=new Handler(){
@Override
public void handleMessage(Message msg) {
//判断广播的四种意图。
super.handleMessage(msg);
switch( msg.what){
case 111:
index=binder.MyStart(index);
break;
case 222:
binder.MyStop();
break;
case 333:
index=binder.MyUp(index);
break;
case 444:
index=binder.MyNext(index);
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化控件
gridView=findViewById(R.id.main_grid);
sb=findViewById(R.id.main_seekBar);
but=findViewById(R.id.main_button_radom);
//判断手机版本
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},205);
}
//开启服务。
Intent it = new Intent(this, MyService.class);
startService(it);
ServiceConnection ss = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder= (MyService.MyBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
bindService(it,ss, Service.BIND_AUTO_CREATE);
//设置条目点击事件
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
index=position;
sb.setMax(Integer.parseInt(read.get(position).getDuration()));
binder.MyStart(position);
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
final int i = binder.GetPosition();
han.post(new Runnable() {
@Override
public void run() {
sb.setProgress(i);
}
});
}
},0,1000);
}
});
//开启广播
IntentFilter itf = new IntentFilter();
//设置意图
itf.addAction("com.notification.start");
itf.addAction("com.notification.pause");
itf.addAction("com.notification.next");
itf.addAction("com.notification.up");
MyReceiver mr = new MyReceiver();
registerReceiver(mr,itf);
//设置进度条滑动监听
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if( fromUser){
binder.Seek(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
//请求权限
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if( requestCode==205&&grantResults[0]== PackageManager.PERMISSION_GRANTED){
read = ReadMyMusic.read(MainActivity.this);
MyAdapter aaa = new MyAdapter(MainActivity.this, read);
gridView.setAdapter(aaa);
}
}
//按钮添加点击事件。
public void click(View view) {
switch( view.getId()) {
case R.id.main_button_start:
binder.MyStart(index);
break;
case R.id.main_button_pause:
binder.MyStop();
break;
case R.id.main_button_next:
if( radomIndex!=-1){
Random random = new Random();
int radomIndex = random.nextInt(read.size() - 1) % (read.size() - 1-0+ 1) + 0;
binder.MyNext(radomIndex);
}else{
index=binder.MyNext(index);
}
break;
case R.id.main_button_up:
if( radomIndex!=-1){
Random random = new Random();
int radomIndex = random.nextInt(read.size() - 1) % (read.size() - 1-0+ 1) + 0;
binder.MyNext(radomIndex);
}else{
index=binder.MyNext(index);
}
break;
case R.id.main_button_radom:
// radomIndex=
/**
* 以产生[10,99]范围内的随机数为例
*
* int min=10;
* int max=99;
* Random random = new Random();
* int num = random.nextInt(max)%(max-min+1) + min;
*/
if( but.getText().equals("随机播放")) {
Random random = new Random();
int radomIndex = random.nextInt(read.size() - 1) % (read.size() - 1 - 0 + 1) + 0;
binder.MyNext(radomIndex);
along=-1;
but.setText("正常播放");
}else if( but.getText().equals("正常播放")){
radomIndex=-1;
but.setText("单曲循环");
index=binder.MyNext(index);
}else if( but.getText().equals("单曲循环")){
along=index;
but.setText("随机播放");
}
break;
}
}
}
自定义服务器
在后台维护音乐播放器
package com.example.mp.MyService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.widget.RemoteViews;
import com.example.mp.MyMusic;
import com.example.mp.R;
import com.example.mp.ReadMyMusic;
import java.io.IOException;
import java.util.List;
public class MyService extends Service {
private List<MyMusic> list;
private MediaPlayer mp;
private int currentPosition;
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
list= ReadMyMusic.read(getApplicationContext());
mp=new MediaPlayer();
mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
}
});
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
NotificationManager ss = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(getApplicationContext());
builder.setSmallIcon(R.mipmap.ic_launcher_round);
RemoteViews rv = new RemoteViews(getPackageName(), R.layout.mynotification);
Intent it1 = new Intent();
it1.setAction("com.notification.start");
PendingIntent broadcast1 = PendingIntent.getBroadcast(getApplicationContext(), 111, it1,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.notification_start,broadcast1);
Intent it2 = new Intent();
it2.setAction("com.notification.pause");
PendingIntent broadcast2 = PendingIntent.getBroadcast(getApplicationContext(), 222, it2,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.notification_pause,broadcast2);
Intent it3 = new Intent();
it3.setAction("com.notification.up");
PendingIntent broadcast3 = PendingIntent.getBroadcast(getApplicationContext(), 333, it3,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.notification_up,broadcast3);
Intent it4 = new Intent();
it4.setAction("com.notification.next");
PendingIntent broadcast4 = PendingIntent.getBroadcast(getApplicationContext(), 444, it4,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.notification_next,broadcast4);
builder.setCustomContentView(rv);
startForeground(310,builder.build());
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
//可以从外部调用该类,并通过里面的方法实现播放和切换音乐的功能。
public class MyBinder extends Binder{
public int MyStart( int position){
return start(position);
}
public void MyStop( ){
stop();
}
public int MyNext( int position){
return next(position);
}
public int MyUp( int position){
return up(position);
}
public int GetPosition( ){
return getPosition();
}
public void Seek( int position){
setSeekTo(position);
}
}
private int start(int position){
mp.reset();
try {
mp.setDataSource(list.get(position).getData());
mp.prepareAsync();
mp.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
return position;
} catch (IOException e) {
e.printStackTrace();
}
return position;
}
private void stop(){
if( mp.isPlaying()) {
mp.pause();
}else{
mp.start();
}
}
private int next(int position){
position++;
if( position>=list.size()){
position=0;
}
return start(position);
}
private int up( int position){
position--;
if( position<0){
position=list.size()-1;
}
return start(position);
}
private int getPosition( ){
if( mp.isPlaying()){
currentPosition= mp.getCurrentPosition();
}
return currentPosition;
}
private void setSeekTo( int position){
if( mp.isPlaying()){
mp.seekTo(position);
}
}
}
广播
通知并能实现控制音乐播放器的操作
package com.example.mp.MyBroadCast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.example.mp.MainActivity;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
if( intent.getAction().equals("com.notification.start")){
MainActivity.han.sendEmptyMessage(111);
}else if(intent.getAction().equals("com.notification.pause")){
MainActivity.han.sendEmptyMessage(222);
}else if( intent.getAction().equals("com.notification.up")){
MainActivity.han.sendEmptyMessage(333);
}else if( intent.getAction().equals("com.notification.next")){
MainActivity.han.sendEmptyMessage(444);
}
}
}
mainActivity布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<GridView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main_grid"
android:numColumns="2"
android:layout_above="@id/main_seekBar"
>
</GridView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/main_linear"
android:orientation="vertical"
android:layout_alignParentBottom="true"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="开始"
android:id="@+id/main_button_start"
android:onClick="click"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暂停"
android:id="@+id/main_button_pause"
android:onClick="click"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="上一首"
android:id="@+id/main_button_up"
android:onClick="click"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="下一首"
android:id="@+id/main_button_next"
android:onClick="click"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="随机播放"
android:id="@+id/main_button_radom"
android:onClick="click"
/>
</LinearLayout>
</LinearLayout>
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/main_linear"
android:id="@+id/main_seekBar"
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
/>
</RelativeLayout>
自定义GridView布局
<?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"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="歌名:"
android:id="@+id/layout_title"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="作曲家:"
android:id="@+id/layout_artist"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="地址:"
android:id="@+id/layout_data"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="大小:"
android:id="@+id/layout_tsize"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时长:"
android:id="@+id/layout_duration"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="编号:"
android:id="@+id/layout_position"
/>
</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="match_parent"
android:orientation="horizontal"
>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="开始"
android:id="@+id/notification_start"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="暂停"
android:id="@+id/notification_pause"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="上一首"
android:id="@+id/notification_up"
/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="下一首"
android:id="@+id/notification_next"
/>
</LinearLayout>
清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mp">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".MyBroadCast.MyReceiver"
android:enabled="false"
android:exported="false"></receiver>
<service
android:name=".MyService.MyService"
android:enabled="true"
android:exported="true" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
原谅博主懒得加注释。