編輯:關於Android編程
Activity代碼
package com.siyehuazhilian.musicplay;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener {
// ListView
private ListView listView;
// 適配器
private SimpleAdapter adapter;
// 數據源
private ArrayList> list;
// 當前播放的曲目
private int currentPositionMusic = -1;
// 上一首
private ImageButton lastImageButton;
// 播放
private ImageButton playImageButton;
// 下一首
private ImageButton nextImageButton;
// 循環
private ImageButton loopImageButton;
// 播放進度
private SeekBar playSeekBar;
// 當前播放曲目
private TextView currentPlayingSong;
// 是否是第一次進來
private boolean ifFirstIn = true;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listview);
lastImageButton = (ImageButton) findViewById(R.id.imagebutton_previous);
playImageButton = (ImageButton) findViewById(R.id.imagebutton_play);
nextImageButton = (ImageButton) findViewById(R.id.imagebutton_next);
loopImageButton = (ImageButton) findViewById(R.id.imagebutton_loops);
playSeekBar = (SeekBar) findViewById(R.id.seekbar_play);
currentPlayingSong = (TextView) findViewById(R.id.textview_songinformation);
list = new ArrayList>();
adapter = new SimpleAdapter(this, list, R.layout.list_item,
new String[] { "title" }, new int[] { R.id.textview_item });
listView.setAdapter(adapter);
// 為listView設置監聽器
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> arg0, View arg1,
int position, long arg3) {
try {
currentPositionMusic = position;
playMusic();
} catch (Exception e) {
e.printStackTrace();
}
}
});
lastImageButton.setOnClickListener(this);
playImageButton.setOnClickListener(this);
nextImageButton.setOnClickListener(this);
loopImageButton.setOnClickListener(this);
playSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if (fromUser) {
// 改變進度條
intent = new Intent("changed");
intent.putExtra("seekbarprogress", progress);
startService(intent);
}
}
});
}
private void playMusic() {
// 啟動播放音樂的服務
intent = new Intent("play");
intent.putExtra("uri", ((HashMap) list
.get(currentPositionMusic)).get("path"));
intent.putExtra("title", ((HashMap) list
.get(currentPositionMusic)).get("title"));
startService(intent);
// 把圖片改為播放的圖片
playImageButton.setImageResource(R.drawable.play);
// 同時更改SeekBar的進度,因為進度是不斷變化的,所以需要一個子線程來刷新下
// playSeekBar.setMax(mp.getDuration());
// 設置當前播放曲目信息
currentPlayingSong.setTextColor(Color.GREEN);
currentPlayingSong.setText(list.get(currentPositionMusic).get("title"));
}
@Override
protected void onResume() {
super.onResume();
// 得到所有音頻
if (ifFirstIn) {
ifFirstIn = false;
scanMusic();
}
// 動態注冊廣播
IntentFilter filter = new IntentFilter();
filter.addAction("seekbarmaxprogress");
filter.addAction("seekbarprogress");
filter.addAction("playNextSong");
filter.addAction("pause");
filter.addAction("setplay");
filter.addAction("stoploop");
filter.addAction("startloop");
registerReceiver(broadcastReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 關閉通知
intent = new Intent("stopnotification");
startService(intent);
// 停止服務
stopService(intent);
// 取消廣播的注冊
unregisterReceiver(broadcastReceiver);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("你確定要退出嗎?");
builder.setPositiveButton("確定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setNegativeButton("取消",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
builder.show();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
/**
* 得多所有的音頻
*/
private void scanMusic() {
// 置空list集合中的所有元素,放置反復啟動導致的數據重復,其實這個部分是因為每次進來都會重新獲得焦點,執行onResume造成的
// 這個修改雖然可以,但是每次進來都有重新加載,增加了手機的符合,所以可以設置一個標志,只有在第一進來的時候才會加載數據
// list.clear();
new Thread() {
public void run() {
Cursor cursor = getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null,
null, null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER);
while (cursor.moveToNext()) {
String title = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.TITLE));
String path = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA));
String size = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE));
if (Long.parseLong(size) > 1024 * 1024) {
HashMap hashMap1 = new HashMap();
hashMap1.put("title", title);
hashMap1.put("path", path);
list.add(hashMap1);
}
}
cursor.close();
};
}.start();
}
/**
* 監聽
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imagebutton_previous:
playLastSong();
break;
case R.id.imagebutton_play:
intent = new Intent("clickplay");
startService(intent);
break;
case R.id.imagebutton_next:
playNextSong();
break;
case R.id.imagebutton_loops:
intent = new Intent("loops");
startService(intent);
break;
default:
break;
}
}
/**
* 播放下一曲
*/
private void playNextSong() {
// 只有當有音樂在播放的時候才可以點擊下一首
if (currentPositionMusic != -1) {
// 如果當前歌曲為最後一首,就播放第一首歌曲
if (currentPositionMusic == list.size() - 1) {
// 設置當前歌曲為第一首
currentPositionMusic = 0;
try {
// 播放第一首歌曲
playMusic();
} catch (Exception e) {
e.printStackTrace();
}
}// 否則就播放下一首歌曲
else {
// 設置當前歌曲為下一首
currentPositionMusic++;
try {
// 播放下一首歌曲
playMusic();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 播放上一曲
*/
private void playLastSong() {
// 只有當有音樂在播放的時候才可以點擊上一首
if (currentPositionMusic != -1) {
// 如果當前歌曲為第一首,就播放最後一首歌曲
if (currentPositionMusic == 0) {
// 設置當前歌曲為最後一首
currentPositionMusic = list.size() - 1;
try {
// 播放最後一首歌曲
playMusic();
} catch (Exception e) {
e.printStackTrace();
}
}// 否則就播放上一首歌曲
else {
// 設置當前歌曲為前一首
currentPositionMusic--;
try {
// 播放前一首歌曲
playMusic();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* 廣播對象,動態注冊,用來接收從Service傳過來的消息,根據不同的消息做不同的事情
*/
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("seekbarmaxprogress")) {
playSeekBar.setMax(intent
.getIntExtra("seekbarmaxprogress", 100));
} else if (intent.getAction().equals("seekbarprogress")) {
playSeekBar.setProgress(intent
.getIntExtra("seekbarprogress", 0));
} else if (intent.getAction().equals("playNextSong")) {
playNextSong();
} else if (intent.getAction().equals("pause")) {
// 還要把圖片改為暫停的圖片
playImageButton.setImageResource(R.drawable.pause);
} else if (intent.getAction().equals("setplay")) {
// 把圖片設置成播放的圖片
playImageButton.setImageResource(R.drawable.play);
} else if (intent.getAction().equals("stoploop")) {
// 還要把圖片改為不循環的圖片
loopImageButton.setImageResource(R.drawable.loop_false);
} else if (intent.getAction().equals("startloop")) {
// 把圖片設置成循環播放的圖片
loopImageButton.setImageResource(R.drawable.loop_true);
}
}
};
}
Service代碼
package com.siyehuazhilian.service;
import java.util.HashMap;
import com.siyehuazhilian.musicplay.MainActivity;
import com.siyehuazhilian.musicplay.R;
import android.annotation.SuppressLint;
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.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.widget.Toast;
public class PlayMusicService extends Service {
private MediaPlayer mediaPlayer;
// 設置Seebar最大進度
private static final int SET_SEEKBAR_MAX = 3;
// 刷新SeekBar進度
private static final int UPDATE_PROGRESS = 1;
// 加載數據
private static final int LOADING_DATA = 2;
// 通知管理
private NotificationManager notificationManager;
// 通知
private Notification notification;
private Intent intent;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@SuppressLint("ShowToast")
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
if (intent.getAction().equals("play")) {// 如果是播放Action,就播放音樂
try {
Toast.makeText(getApplicationContext(), "開始播放", 1000).show();
playMusic(intent.getStringExtra("uri"));
showNotification(intent.getStringExtra("title"));
} catch (Exception e) {
e.printStackTrace();
}
} else if (intent.getAction().equals("changed")) {// 如果是拖動的Action,就跳至拖動的進度
if (mediaPlayer != null) {
mediaPlayer.seekTo(intent.getIntExtra("seekbarprogress", 0));
}
} else if (intent.getAction().equals("clickplay")) {// 如果是播放/暫停Action,就執行相應的播放或者暫停
Toast.makeText(getApplicationContext(), "播放被點擊了", 1000).show();
if (mediaPlayer != null) {
// 如果音樂播放器正在播放
if (mediaPlayer.isPlaying()) {
// 那就暫停它
mediaPlayer.pause();
// 發送暫停廣播給程序
this.intent = new Intent("pause");
sendBroadcast(this.intent);
} else {
// 否則就播放它
mediaPlayer.start();
// 發送播放廣播
this.intent = new Intent("setplay");
sendBroadcast(this.intent);
}
}
} else if (intent.getAction().equals("loops")) {// 如果是loop循環Action,就把歌曲設置為循環播放
Toast.makeText(getApplicationContext(), "循環被點擊了", 1000).show();
if (mediaPlayer != null) {
// 如果音樂播放器正在循環
if (mediaPlayer.isLooping()) {
// 那就終止循環它
mediaPlayer.setLooping(false);
// 發送終止循環廣播
this.intent = new Intent("stoploop");
sendBroadcast(this.intent);
} else {
// 否則就循環播放它
mediaPlayer.setLooping(true);
// 發送開始循環廣播
this.intent = new Intent("startloop");
sendBroadcast(this.intent);
}
}
} else if (intent.getAction().equals("stopnotification")) {
notificationManager.cancelAll();
}
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
handler.removeMessages(UPDATE_PROGRESS);
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
/**
* 播放音樂
*
* @param path
* @throws Exception
*/
private void playMusic(String path) throws Exception {
if (mediaPlayer == null) {
// 新建一個mediaPalyer對象
mediaPlayer = new MediaPlayer();
}
// 使mediaPalyer進入Idle狀態
mediaPlayer.reset();
// 設置數據源,使mediaPlayer進入Intialized狀態
mediaPlayer.setDataSource(path);
// 准備播放
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
// 開始播放音樂
mp.start();
handler.sendEmptyMessage(SET_SEEKBAR_MAX);
handler.sendEmptyMessage(UPDATE_PROGRESS);
}
});
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mp.isLooping()) {
mp.start();
} else {
intent = new Intent("playNextSong");
sendBroadcast(intent);
}
}
});
}
private Handler handler = new Handler() {
@SuppressLint("HandlerLeak")
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_PROGRESS:
// 設置最大當前播放進度
intent = new Intent("seekbarprogress");
intent.putExtra("seekbarprogress",
mediaPlayer.getCurrentPosition());
sendBroadcast(intent);
// 需要隨著播放設置
handler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 1000);
break;
case LOADING_DATA:
// adapter.notifyDataSetInvalidated();
break;
case SET_SEEKBAR_MAX:
intent = new Intent("seekbarmaxprogress");
intent.putExtra("seekbarmaxprogress", mediaPlayer.getDuration());
sendBroadcast(intent);
// 因為進度條只需要設置一次就夠了,所以不需要反復發送Message;
break;
default:
break;
}
};
};
/**
* 顯示通知
*
*/
private void showNotification(String title) {
notification = new Notification(R.drawable.app_icon, "百度音樂",
System.currentTimeMillis());
notification.flags |= Notification.FLAG_NO_CLEAR;
notification.flags |= Notification.FLAG_ONGOING_EVENT;
Intent intent = new Intent(this, MainActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
intent, 0);
notification.setLatestEventInfo(this, "正在播放", title, pendingIntent);
notificationManager.notify(1, notification);
}
}
AndroidManifest.xml代碼
Android 磁盤緩存 DiskLruCache
上一篇講了內存緩存,這一篇就緊接著講一下磁盤緩存DiskLruCache.官方文檔:https://developer.android.com/training/disp
Android應用中使用SharedPreferences類存儲數據的方法
在Android系統中提供了多種存儲技術.通過這些存儲技術可以將數據存儲在各種存儲介質上.比如sharedpreferences可以將數據保存著應用軟件的私有存儲區,這些
Android自定義View之仿QQ側滑菜單實現
最近,由於正在做的一個應用中要用到側滑菜單,所以通過查資料看視頻,學習了一下自定義View,實現一個類似於QQ的側滑菜單,順便還將其封裝為自定義組件,可以實現類似QQ的側
Android仿聯系人列表分組懸浮列表,PinnedHeaderListView源碼解析
github地址:https://github.com/JimiSmith/PinnedHeaderListView 關於實現類似聯系人列表,組的頭部總是懸浮在list