onCreat到onDestroy是整个activity生命周期(界面生成代码放在oncreate,放其他循环占内存);onStart到onStop是所有在显示界面的周期(onRestart完成循环,例如:返回列表信息时应该更新内容);onResume到onPause一次显示在界面的周期;
播放歌曲时,进度条要动,而且下面的值也变化,所以用多线程,
照完照片存sd卡然后添加到头像,布局xml写在前面的是放在最下面(存在布满整个界面的情况下)
可以在官网,也可以在下载下来的sdk中查看api。D:\Android4.0\adt-bundle-windows-x86-20130219\sdk\docs\reference
主activity代码
package com.kane.musicplayer;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import com.kane.musicplayer.dbc.SqliteConnection;
import com.kane.musicplayer.util.MusicDAOUtils;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.R.integer;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private MediaPlayer player;
//上一首,播放,下一首
private Button preBtn,nextBtn,playBtn;
//歌曲名称,显示时间/歌曲总时间
private TextView songName,timeText;
private SeekBar seekBar;
//总时长的文字
private String allTimeText;
//加入子线程的通道
private Handler handler;
//取得所有播放歌曲的集合
private List<Map<String,Object>> allValues;
private SqliteConnection sc;
private String filePath="/mnt/sdcard/Music/a.mp3";
private String name="FLY ME TO THE MOOM";
//当前播放歌曲索引
private int playIndex=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//建立数据库连接
sc=new SqliteConnection(this);
//读取数据库中的保存而定音乐播放列表
allValues=MusicDAOUtils.listdata(sc.getReadableDatabase());
// 初始化所有组件
preBtn = (Button) findViewById(R.id.pre_btn);
playBtn = (Button) findViewById(R.id.play_btn);
nextBtn = (Button) findViewById(R.id.next_btn);
songName = (TextView) findViewById(R.id.song_name);
timeText = (TextView) findViewById(R.id.time_text);
seekBar = (SeekBar) findViewById(R.id.seekbar);
/**
* 这里歌曲在播放,同时进度条和时间进度应该在走,涉及多线程
*/
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
//进度条前进的位置
seekBar.setProgress(player.getCurrentPosition());
timeText.setText(changeToTimeFormat(player.getCurrentPosition())+"/"+
allTimeText);
}
};
//初始化第一首歌曲
setPlayMusic();
//设置player.setLooping(false);不循环
// player.setVolume(1.0f, 1.0f);左右声道音量
//播放
playBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (player.isPlaying()) {
player.pause();
playBtn.setBackgroundResource(R.drawable.bt_widget_play_nor);
}
else {//暂停状态
player.start();
playBtn.setBackgroundResource(R.drawable.bt_widget_pause_nor);
}
}
});
//拖动,并改变播放位置,音乐动。进度条和显示时间一起走
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//拖到一点,放手
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// 根据当前SeekBar的位置,让播放器从这个位置开始播放
player.seekTo(seekBar.getProgress());
//重新播放音乐
player.start();
}
//在拖动中
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//暂停播放音乐
if (player.isPlaying()) {
player.pause();
}
}
/**
* 进度条改变,fromUser可以是某个人操作,也可以是系统
* progress 是当前位置
*/
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// 时间跟着进度条一起走, 前提是用户改变的时候.
if (fromUser) {
timeText.setText(changeToTimeFormat(progress)+"/"
+allTimeText);
}
}
});
// 进行歌曲的切换
preBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (playIndex == 0) {
Toast.makeText(MainActivity.this, "当前已经是第一首歌,无法切换上一首!",
Toast.LENGTH_LONG).show();
} else {
playIndex--;
setPlayMusic();
playBtn.performClick();//播放按钮的点击操作即播放
}
}
});
nextBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (playIndex == allValues.size() - 1) {
Toast.makeText(MainActivity.this, "当前已经是最后一首歌,无法切换下一首!",
Toast.LENGTH_LONG).show();
} else {
playIndex++;
setPlayMusic();
playBtn.performClick();//播放按钮的点击操作即播放
}
}
});
//加入一个子线程,控制拖动条的自动移动,上面写的监听事件可以是主线程的也可以是子线程的
//子线程要改变界面要用到handler
Thread t=new Thread(){
public void run() {
try {
while (true) {
sleep(1000);//间隔1秒查询一次是否移动
//如果已经播放,就移动拖动条,否则不用移动
if (player.isPlaying()) {
handler.sendEmptyMessage(0);
}
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
t.start();
}
/**
* 进行音乐初始化,初始状态是停止
*/
public void setPlayMusic() {
Map<String,Object> map=allValues.get(playIndex);
filePath=map.get("filePath").toString();
name=map.get("songName").toString();
if(player!=null){
if (player.isPlaying()) {
player.stop();
}
player.release();//先停止,后释放内存
}
//先建立player对象
player=new MediaPlayer();
try {
//设置数据来源。可以在官网,也可以在下载下来的sdk中查看api。D:\Android4.0\adt-bundle-windows-x86-20130219\sdk\docs\reference
// player = MediaPlayer.create(this, R.raw.a);放在项目内的,可以不用prepare
player.setDataSource(this, Uri.fromFile(new File(filePath)));
songName.setText(name);
//准备
player.prepare();
//获取整个音频的长度,ms单位
allTimeText=changeToTimeFormat(player.getDuration());
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Toast.makeText(MainActivity.this, "播放出现问题, 请与needkane联系",
Toast.LENGTH_SHORT).show();
}
//设置最大值
seekBar.setMax(player.getDuration());
//显示初始进来的 播放时间/总时间,初始状态是停止
timeText.setText("00:00:00/"+allTimeText);
}
/**
* 将ms转成hh:mm:ss的格式
* @param ms
* @return
*/
public String changeToTimeFormat(int ms) {
int s=ms/1000;
int min=s/60;
s=s%60;//多出的秒数
int hour=min/60;
min=min%60;
StringBuilder sb=new StringBuilder();
if (hour<10) {//如果hour小于10,前面应该加0
sb.append("0");
}
sb.append(hour+":");
if (min<10) {
sb.append("0");
}
sb.append(min+":");
if (s<10) {
sb.append("0");
}
sb.append(s);
return sb.toString();
}
@Override
protected void onDestroy() {
//退出时释放播放的音乐
try {
if (player!=null) {
if (player.isPlaying()) {
player.stop();
}
player.release();
}
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.onDestroy();
}
}
数据库连接和操作代码
package com.kane.musicplayer.dbc;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
public class SqliteConnection extends SQLiteOpenHelper {
private static String DBNAME="music.db";
public SqliteConnection(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
// TODO Auto-generated constructor stub
}
public SqliteConnection(Context ctx) {
super(ctx, DBNAME, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql="CREATE TABLE music(" +
"filepath text primary key," +
"songname text " +
")";
db.execSQL(sql);
//这里的音频我们手动插入的,实际情况应该是下载到sdcard
sql = "INSERT INTO music (filepath,songname) VALUES (‘/mnt/sdcard/Music/a.mp3‘,‘Fly me to the moon‘)" ;
db.execSQL(sql);
sql = "INSERT INTO music (filepath,songname) VALUES (‘/mnt/sdcard/Music/b.mp3‘,‘时间都去哪儿了‘)" ;
db.execSQL(sql);
sql = "INSERT INTO music (filepath,songname) VALUES (‘/mnt/sdcard/Music/c.mp3‘,‘卷珠帘‘)" ;
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
package com.kane.musicplayer.util;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
public class MusicDAOUtils {
public static List<Map<String, Object>> listdata(SQLiteDatabase sc) {
String sql="SELECT filepath,songname FROM music";
List<Map<String, Object>> allValues = new ArrayList<Map<String, Object>>();
Cursor c=sc.rawQuery(sql,null);//rawQuery里面执行sql语句
c.moveToFirst();//手动指向第一个
while (!c.isAfterLast()) {//当不是最后一个的时候
Map<String,Object> map=new HashMap<String, Object>();
map.put("filePath",c.getString(0));
map.put("songName", c.getString(1));
allValues.add(map);
c.moveToNext();//手动指向下一个
}
c.close();
return allValues;
}
}
界面代码
<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="#000000"
android:orientation="vertical" >
<TextView
android:id="@+id/song_name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:gravity="center"
android:layout_weight="1"
android:textColor="#ffffff"
android:textSize="16sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
<SeekBar
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5" />
<TextView
android:id="@+id/time_text"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="0.5"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2.5" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal" >
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5" />
<Button
android:id="@+id/pre_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/bt_widget_prev_nor" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:id="@+id/play_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.5"
android:background="@drawable/bt_widget_play_nor" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<Button
android:id="@+id/next_btn"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/bt_widget_next_nor" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5" />
</LinearLayout>
</LinearLayout>
android音乐播放器;activity生命周期;模拟器用快照(snapshot)没声音;win7要用管理员身份运行adt,才能打开模拟器sdcard;,布布扣,bubuko.com
android音乐播放器;activity生命周期;模拟器用快照(snapshot)没声音;win7要用管理员身份运行adt,才能打开模拟器sdcard;