溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

android通過(guò)SQLite數(shù)據(jù)庫(kù)的操作如何實(shí)現(xiàn)音樂(lè)播放器

發(fā)布時(shí)間:2021-11-30 17:23:15 來(lái)源:億速云 閱讀:179 作者:柒染 欄目:數(shù)據(jù)庫(kù)

android通過(guò)SQLite數(shù)據(jù)庫(kù)的操作如何實(shí)現(xiàn)音樂(lè)播放器,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

下面實(shí)現(xiàn)播放列表的功能。

當(dāng)選擇某一首歌曲后,自動(dòng)將該歌曲加入到整個(gè)播放列表中,每次進(jìn)入播放歌曲的界面時(shí),查詢出所有的播放列表中的歌曲,并加入到ListView里,供用戶選擇。

這樣就需要建立一張歌曲表,保存所有的歌曲,主鍵是歌曲的完整路徑。

具體的效果:

第一,先進(jìn)入到sdcard中

android通過(guò)SQLite數(shù)據(jù)庫(kù)的操作如何實(shí)現(xiàn)音樂(lè)播放器

然后,選擇一個(gè)map3音樂(lè),進(jìn)入到播放頁(yè)面,這里實(shí)現(xiàn)是通過(guò)先將數(shù)據(jù)的路勁和名稱存入數(shù)據(jù)庫(kù),然后再讀取數(shù)據(jù)庫(kù)中的音樂(lè)信息,完成的

android通過(guò)SQLite數(shù)據(jù)庫(kù)的操作如何實(shí)現(xiàn)音樂(lè)播放器

代碼實(shí)現(xiàn):首先是activity_main.xml

<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="#cccccc"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/music_name"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center"
        android:text="@string/hello_world"
        android:textColor="#000000"
        android:textSize="16sp" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:background="@drawable/audio_identify_start_default" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3" >
    </ListView>

    <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_weight="0.5"
        android:gravity="center"
        android:text="00:00 / 00:00"
        android:textColor="#000000"
        android:textSize="12sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center" />

    <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/ic_player_prev_default" />

        <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/ic_player_play_default" />

        <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/ic_player_next_default" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="0.5" />
    </LinearLayout>

</LinearLayout>

這里實(shí)現(xiàn)的是播放器的頁(yè)面。

然后是實(shí)現(xiàn)數(shù)據(jù)處理的xml,song_line.xml

<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="wrap_content"
    android:background="#ffffff" >

    <TextView
        android:id="@+id/song_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#000000"
        android:textSize="14sp" >
    </TextView>

</LinearLayout>

然后是activity_file_list.xml,這是實(shí)現(xiàn)sdcard頁(yè)面的顯示

<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:orientation="vertical" >

    <TextView
        android:id="@+id/title_text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="center_vertical"
        android:text="當(dāng)前位置: /mnt/sdcard"
        android:textSize="14sp" />

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="8"
        android:cacheColorHint="#00000000" >
    </ListView>

</LinearLayout>

然后是實(shí)現(xiàn)sdcard頁(yè)面數(shù)據(jù)的xml,fine_line.xml

<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="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/file_img"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <TextView
        android:id="@+id/file_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="4"
        android:textSize="14sp" />

</LinearLayout>

第二步,java代碼,首先實(shí)現(xiàn)數(shù)據(jù)庫(kù)的創(chuàng)建

package org.liky.music.util;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DataBaseConnection extends SQLiteOpenHelper {

	public DataBaseConnection(Context ctx) {
		super(ctx, "music.db", null, 1);
	}
	
	public DataBaseConnection(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// 建立表
		String sql = "CREATE TABLE music (" +
				"full_path			text			primary key ," +
				"song_name			text			" +
				");" ;
		
		db.execSQL(sql);
	}

然后是公共類初始化的一些設(shè)置Global,如控制屏幕顯示的

package org.liky.music.util;

import java.util.HashMap;
import java.util.Map;

import org.liky.music.R;

import android.app.Activity;
import android.os.Environment;

public class Globals {

	public static int SCREEN_WIDTH;
	public static int SCREEN_HEIGHT;
	// 建立一個(gè)Map集合, 里面封裝了所有擴(kuò)展名對(duì)應(yīng)的圖標(biāo)圖片, 以便進(jìn)行文件圖標(biāo)的顯示
	public static Map<String, Integer> allIconImgs = new HashMap<String, Integer>();

	public static Map<String, String> allSongNameMap = new HashMap<String, String>();

	// 初始化數(shù)據(jù)庫(kù)連接
	public static DataBaseConnection dbc;

	public static void init(Activity a) {
		SCREEN_WIDTH = a.getWindowManager().getDefaultDisplay().getWidth();
		SCREEN_HEIGHT = a.getWindowManager().getDefaultDisplay().getHeight();

		dbc = new DataBaseConnection(a);
		
		// 初始化一些歌曲名稱
		allSongNameMap.put("/storage/sdcard/a.mp3", "Fly Me To The Moon");
		allSongNameMap.put("/storage/sdcard/b.mp3", "時(shí)間都去哪兒了");
		allSongNameMap.put("/storage/sdcard/c.mp3", "卷珠簾");

		// 初始化所有擴(kuò)展名和圖片的對(duì)應(yīng)關(guān)系
		allIconImgs.put("txt", R.drawable.txt_file);
		allIconImgs.put("mp3", R.drawable.mp3_file);
		allIconImgs.put("mp4", R.drawable.mp4_file);
		allIconImgs.put("bmp", R.drawable.image_file);
		allIconImgs.put("gif", R.drawable.image_file);
		allIconImgs.put("png", R.drawable.image_file);
		allIconImgs.put("jpg", R.drawable.image_file);
		allIconImgs.put("dir_open", R.drawable.open_dir);
		allIconImgs.put("dir_close", R.drawable.close_dir);
	}

}

然后是對(duì)數(shù)據(jù)庫(kù)SQLite的數(shù)據(jù)的創(chuàng)建和更新;

package org.liky.music.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.database.Cursor;

public class MusicDAOUtils {

	public static void insertData(String fullPath) {
		// 先判斷數(shù)據(jù)庫(kù)中是否有這條數(shù)據(jù)
		String sql = "SELECT song_name FROM music WHERE full_path = ?";
		Cursor c = Globals.dbc.getReadableDatabase().rawQuery(sql,
				new String[] { fullPath });
		if (!c.moveToFirst()) {
			// 之前沒(méi)有添加過(guò),需要添加新數(shù)據(jù)
			sql = "INSERT INTO music VALUES (?,?)";
			Globals.dbc.getWritableDatabase().execSQL(
					sql,
					new Object[] { fullPath,
							Globals.allSongNameMap.get(fullPath) });
		}
		c.close();
	}

	public static List<Map<String, Object>> listData() {
		String sql = "SELECT full_path,song_name FROM music";
		Cursor c = Globals.dbc.getReadableDatabase().rawQuery(sql, null);

		List<Map<String, Object>> allValues = new ArrayList<Map<String, Object>>();
		c.moveToFirst();
		while (!c.isAfterLast()) {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("fullPath", c.getString(0));
			map.put("songName", c.getString(1));
			allValues.add(map);

			c.moveToNext();
		}

		c.close();

		return allValues;
	}
}

第三步,創(chuàng)建adapter,兩個(gè)簡(jiǎn)單的adapter,處理文件,和音樂(lè)

package org.liky.music.adapter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.liky.music.R;
import org.liky.music.util.Globals;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class FileAdapter extends BaseAdapter {

	private Context ctx;
	private List<Map<String, Object>> allValues = new ArrayList<Map<String, Object>>();

	public FileAdapter(Context ctx, List<Map<String, Object>> allValues) {
		this.ctx = ctx;
		this.allValues = allValues;
	}

	@Override
	public int getCount() {
		return allValues.size();
	}

	@Override
	public Object getItem(int arg0) {
		return allValues.get(arg0);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if (convertView == null) {
			convertView = LayoutInflater.from(ctx).inflate(R.layout.file_line,
					null);
			// 設(shè)置高度
			convertView.setLayoutParams(new LayoutParams(
					LayoutParams.MATCH_PARENT, Globals.SCREEN_HEIGHT / 9));
		}

		// 取得組件
		TextView fileImg = (TextView) convertView.findViewById(R.id.file_img);

		fileImg.getLayoutParams().height = Globals.SCREEN_HEIGHT / 9;

		TextView fileName = (TextView) convertView.findViewById(R.id.file_name);

		// 取得數(shù)據(jù),設(shè)置到組件里
		Map<String, Object> map = allValues.get(position);

		// 設(shè)置內(nèi)容, 文字
		fileName.setText(map.get("fileName").toString());

		// 圖片要根據(jù)擴(kuò)展名取得
		String extName = map.get("extName").toString();
		// 取得圖片的id
		int imgId = Globals.allIconImgs.get(extName);
		// 設(shè)置圖片
		fileImg.setBackgroundResource(imgId);

		return convertView;
	}

}
package org.liky.music.adapter;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.liky.music.R;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MusicAdapter extends BaseAdapter {

	private List<View> allViews = new ArrayList<View>();

	private Context ctx;

	public MusicAdapter(List<Map<String, Object>> allValues, Context ctx) {
		this.ctx = ctx;
		// 循環(huán)建立View
		Iterator<Map<String, Object>> iter = allValues.iterator();
		while (iter.hasNext()) {
			Map<String, Object> map = iter.next();

			View v = LayoutInflater.from(ctx).inflate(R.layout.song_line, null);
			TextView songName = (TextView) v.findViewById(R.id.song_name);
			songName.setText(map.get("songName").toString());

			allViews.add(v);
		}
	}

	public void setSelectedBackground(int index) {
		// 其他的索引全部清空成為白色
		for (int i = 0; i < allViews.size(); i++) {
			if (i == index) {
				allViews.get(index).setBackgroundColor(Color.RED);
			} else {
				allViews.get(i).setBackgroundColor(Color.WHITE);
			}
		}
	}

	@Override
	public int getCount() {
		return allViews.size();
	}

	@Override
	public Object getItem(int position) {
		return allViews.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		return allViews.get(position);
	}

}

最后是實(shí)現(xiàn)的Activity,FIleListActivity和mainActivity

package org.liky.music;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.liky.music.adapter.FileAdapter;
import org.liky.music.util.Globals;
import org.liky.music.util.MusicDAOUtils;

import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.TextView;

public class FileListActivity extends Activity {

	private TextView titleText;
	private ListView list;

	private FileAdapter adapter;
	private List<Map<String, Object>> allValues = new ArrayList<Map<String, Object>>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		Globals.init(this);

		setContentView(R.layout.activity_file_list);

		// 取得組件
		titleText = (TextView) findViewById(R.id.title_text);
		list = (ListView) findViewById(R.id.list);

		// 準(zhǔn)備數(shù)據(jù)
		// 取得SD卡根目錄
		File root = Environment.getExternalStorageDirectory();

		loadFileData(root);

		// 建立Adapter
		adapter = new FileAdapter(this, allValues);

		list.setAdapter(adapter);

		// 加入監(jiān)聽(tīng)事件
		list.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// 取得當(dāng)前操作的數(shù)據(jù)
				Map<String, Object> map = allValues.get(arg2);
				// 判斷所點(diǎn)的是文件還是文件夾
				boolean dirFlag = (Boolean) map.get("dirFlag");
				if (dirFlag) {
					// 文件夾
					// 建立該文件夾的File對(duì)象
					// 取得絕對(duì)路徑
					String fullPath = (String) map.get("fullPath");
					// 建立File
					File dir = new File(fullPath);

					// 先清空原有數(shù)據(jù)
					allValues.clear();

					if (!Environment.getExternalStorageDirectory()
							.getAbsolutePath().equals(fullPath)) {
						// 加入返回上一級(jí)的操作行
						Map<String, Object> parent = new HashMap<String, Object>();
						parent.put("fileName", "返回上一級(jí)");
						parent.put("extName", "dir_open");
						parent.put("dirFlag", true);
						parent.put("fullPath", dir.getParent());

						// 保存一個(gè)標(biāo)志
						parent.put("flag", "TRUE");

						// 將這一行加入到數(shù)據(jù)集合中
						allValues.add(parent);
					}

					// 加入新數(shù)據(jù)
					loadFileData(dir);

					// 使用Adapter通知界面ListView,數(shù)據(jù)已經(jīng)被修改了,你也要一起改
					adapter.notifyDataSetChanged();
				} else {
					// 點(diǎn)某個(gè)文件時(shí),將該文件完整路徑傳入到MainActivity中
					String fullPath = map.get("fullPath").toString();
					// 將數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中
					MusicDAOUtils.insertData(fullPath);

					Intent in = new Intent(FileListActivity.this,
							MainActivity.class);
					in.putExtra("fullPath", fullPath);
					startActivity(in);
				}

			}
		});

		list.setOnItemLongClickListener(new OnItemLongClickListener() {
			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					final int arg2, long arg3) {
				// 取得數(shù)據(jù)
				Map<String, Object> map = allValues.get(arg2);
				final File f = new File(map.get("fullPath").toString());

				if (f.isFile()) {
					// 彈出確認(rèn)框
					Builder builder = new Builder(FileListActivity.this);
					builder.setTitle("提示");
					builder.setMessage("確定要?jiǎng)h除該文件(" + f.getName() + ")嗎?");
					builder.setPositiveButton("確定", new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// 將SD卡中的文件刪除
							if (f.exists()) {
								f.delete();
							}

							// 將列表中的數(shù)據(jù)刪除
							allValues.remove(arg2);
							// 通知
							adapter.notifyDataSetChanged();
						}
					});
					builder.setNegativeButton("取消", new OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
						}
					});

					builder.create().show();
				}

				return false;
			}
		});

	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// 根據(jù)keyCode判斷用戶按下了哪個(gè)鍵
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			// 判斷當(dāng)前是否在SD卡跟目錄.
			// 取得第一行數(shù)據(jù)
			Map<String, Object> map = allValues.get(0);
			if ("TRUE".equals(map.get("flag"))) {
				// 里面,需要返回上一級(jí)
				list.performItemClick(list.getChildAt(0), 0, list.getChildAt(0)
						.getId());
			} else {
				// 彈出提示框
				Builder builder = new Builder(FileListActivity.this);
				builder.setTitle("提示");
				builder.setMessage("親,真的要離開(kāi)我嗎?");
				builder.setPositiveButton("真的", new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						// 關(guān)閉當(dāng)前Activity
						finish();
					}
				});
				builder.setNegativeButton("再待會(huì)兒", new OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {

					}
				});
				builder.create().show();
			}

			return false;
		}

		return super.onKeyDown(keyCode, event);
	}

	private void loadFileData(File dir) {
		// 列出該目錄下的所有文件
		File[] allFiles = dir.listFiles();
		// 設(shè)置當(dāng)前位置的提示信息
		titleText.setText("當(dāng)前位置: " + dir.getAbsolutePath());

		// 判斷
		if (allFiles != null) {
			// 循環(huán)
			for (int i = 0; i < allFiles.length; i++) {
				File f = allFiles[i];
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("fileName", f.getName());
				// 多保存一個(gè)文件的絕對(duì)路徑,方便在進(jìn)行點(diǎn)擊時(shí)使用
				map.put("fullPath", f.getAbsolutePath());
				// 判斷是文件夾還是文件
				if (f.isDirectory()) {
					// 是文件夾
					map.put("extName", "dir_close");
					map.put("dirFlag", true);
				} else {
					// 是文件
					// 截取出擴(kuò)展名
					String extName = f.getName()
							.substring(f.getName().lastIndexOf(".") + 1)
							.toLowerCase();
					map.put("extName", extName);
					map.put("dirFlag", false);
				}

				// 只添加文件夾或所有mp3文件
				if (f.isDirectory() || "mp3".equals(map.get("extName"))) {
					allValues.add(map);
				}
			}
		}
	}

}
package org.liky.music;

import java.util.List;
import java.util.Map;

import org.liky.music.adapter.MusicAdapter;
import org.liky.music.util.MusicDAOUtils;

import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
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 String filePath = "/storage/sdcard/a.mp3";
	private String songName = "Fly Me To The Moon";
	// 準(zhǔn)備ListView
	private ListView list;
	private MusicAdapter adapter;
	private List<Map<String, Object>> allValues;

	// 當(dāng)前播放的歌曲索引
	private int playingIndex = 0;

	// 音樂(lè)名稱
	private TextView musicName;
	// 播放時(shí)間長(zhǎng)度的文本
	private TextView timeText;
	// 拖動(dòng)條
	private SeekBar seekbar;
	// 播放/暫停 按鈕
	private Button playBtn;
	// 上一首
	private Button preBtn;
	// 下一首
	private Button nextBtn;

	// 總播放時(shí)長(zhǎng)的文本
	private String durationTimeStr;

	// 建立消息通道,以便在子線程中修改界面
	private Handler handler;

	// 線程對(duì)象,監(jiān)聽(tīng)拖動(dòng)條的移動(dòng)
	private Thread t = null;

	private boolean flag = true;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		player = new MediaPlayer();

		// 接收傳入的文件路徑
		filePath = getIntent().getStringExtra("fullPath");
		// songName = Globals.allSongNameMap.get(filePath);

		// 提取所有歌曲數(shù)據(jù),并初始化
		allValues = MusicDAOUtils.listData();

		// 判斷當(dāng)前應(yīng)該播放的是列表中的哪一首
		for (int i = 0; i < allValues.size(); i++) {
			if (allValues.get(i).get("fullPath").equals(filePath)) {
				// 該歌曲就是要進(jìn)行播放的歌曲
				playingIndex = i;
				songName = allValues.get(i).get("songName").toString();
				break;
			}
		}

		// 將數(shù)據(jù)放入到listView中列表
		list = (ListView) findViewById(R.id.list);

		adapter = new MusicAdapter(allValues, this);

		list.setAdapter(adapter);

		// 設(shè)置選中的背景
		adapter.setSelectedBackground(playingIndex);

		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				seekbar.setProgress(player.getCurrentPosition());
				timeText.setText(getTextByMs(player.getCurrentPosition()) + "/"
						+ durationTimeStr);
			}
		};

		// 取得所有組件
		musicName = (TextView) findViewById(R.id.music_name);
		timeText = (TextView) findViewById(R.id.time_text);

		seekbar = (SeekBar) findViewById(R.id.seekbar);

		playBtn = (Button) findViewById(R.id.play_btn);
		preBtn = (Button) findViewById(R.id.pre_btn);
		nextBtn = (Button) findViewById(R.id.next_btn);

		// 初始化

		// 加入一個(gè)多線程,通過(guò)子線程控制拖動(dòng)條以及顯示時(shí)間的改變
		t = new Thread() {
			@Override
			public void run() {
				while (flag) {
					try {
						Thread.sleep(1000);

						// 取得當(dāng)前的播放時(shí)間位置,設(shè)置到拖動(dòng)條里
						if (player.isPlaying()) {
							// 傳遞一個(gè)空消息,不需要有具體的消息內(nèi)容,因?yàn)橄⑼ǖ乐兄挥幸粋€(gè)固定的操作,而且不需要參數(shù).
							handler.sendEmptyMessage(0);
						}

					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		};
		t.start();

		// 播放歌曲
		playSong();

		// 為播放按鈕加監(jiān)聽(tīng)
		playBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				if (player.isPlaying()) {
					player.pause();
					playBtn.setBackgroundResource(R.drawable.ic_player_play_default);
				} else {
					player.start();
					playBtn.setBackgroundResource(R.drawable.ic_player_pause_default);
				}
			}
		});

		// 開(kāi)始播放
		playBtn.performClick();

		// 加入拖動(dòng)條的監(jiān)聽(tīng)
		seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {
				// 開(kāi)始播放, 同時(shí)要倒到當(dāng)前拖動(dòng)條的位置
				player.seekTo(seekbar.getProgress());
				player.start();
				// 修改按鈕的圖片
				playBtn.setBackgroundResource(R.drawable.ic_player_pause_default);
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
				// 暫停播放
				player.pause();
				playBtn.setBackgroundResource(R.drawable.ic_player_play_default);
			}

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				// 如果是因?yàn)槿藶橥蟿?dòng)造成的值改變,則時(shí)間文本需要一起修改,如果是自動(dòng)改變的拖動(dòng)條的值,則不需要修改
				if (fromUser) {
					// 修改顯示時(shí)間的數(shù)據(jù)
					timeText.setText(getTextByMs(progress) + "/"
							+ durationTimeStr);
				}
			}
		});

		// 設(shè)置點(diǎn)某一首歌,進(jìn)行重新播放的功能
		list.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// 如果是當(dāng)前正在播放的歌曲,不需要處理
				if (arg2 != playingIndex) {
					// 播放當(dāng)前所點(diǎn)擊的歌曲
					playingIndex = arg2;
					// 重新播放歌曲
					playSong();
					// 播放歌曲
					player.start();
					playBtn.setBackgroundResource(R.drawable.ic_player_pause_default);
					// 重新設(shè)置默認(rèn)選中的歌曲
					adapter.setSelectedBackground(playingIndex);
				}

			}
		});

		// 設(shè)置播放上一首和下一首的功能
		preBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 判斷當(dāng)前是否在播放第一首
				if (playingIndex == 0) {
					Toast.makeText(MainActivity.this, "當(dāng)前已經(jīng)播放的是第一首歌,沒(méi)有前一首!",
							Toast.LENGTH_SHORT).show();
				} else {
					list.performItemClick((View) adapter
							.getItem(playingIndex - 1), playingIndex - 1,
							((View) (adapter.getItem(playingIndex - 1)))
									.getId());
				}
			}
		});
		nextBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// 判斷當(dāng)前是否在播放最后一首
				if (playingIndex == allValues.size() - 1) {
					Toast.makeText(MainActivity.this, "當(dāng)前已經(jīng)播放的是最后一首歌,沒(méi)有后一首!",
							Toast.LENGTH_SHORT).show();
				} else {
					list.performItemClick((View) adapter
							.getItem(playingIndex + 1), playingIndex + 1,
							((View) (adapter.getItem(playingIndex + 1)))
									.getId());
				}
			}
		});

		// 加入播放完成后,自動(dòng)播放下一首歌的功能
		player.setOnCompletionListener(new OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer mp) {
				// 自動(dòng)播放下一首歌,如果已經(jīng)是最后一首,直接播放第一首
				if (playingIndex == allValues.size() - 1) {
					list.performItemClick((View) adapter.getItem(0), 0,
							((View) (adapter.getItem(0))).getId());
				} else {
					list.performItemClick((View) adapter
							.getItem(playingIndex + 1), playingIndex + 1,
							((View) (adapter.getItem(playingIndex + 1)))
									.getId());
				}

			}
		});

	}

	private void playSong() {
		filePath = allValues.get(playingIndex).get("fullPath").toString();
		songName = allValues.get(playingIndex).get("songName").toString();

		// 如果正在播放,則停止播放
		if (player.isPlaying()) {
			player.stop();
		}

		// 重置
		player.reset();

		try {
			// 設(shè)置要播放的文件
			player.setDataSource(filePath);
			// 進(jìn)行準(zhǔn)備操作
			player.prepare();
			// player.start();

			// 初始化拖動(dòng)條的總長(zhǎng)度
			seekbar.setMax(player.getDuration());
			seekbar.setProgress(0);

			durationTimeStr = getTextByMs(player.getDuration());

			// 修改歌曲標(biāo)題
			musicName.setText(songName);

			// 設(shè)置顯示的播放時(shí)間
			timeText.setText("00:00 / " + durationTimeStr);

		} catch (Exception e) {
			e.printStackTrace();
			Toast.makeText(this, "當(dāng)前加載的音樂(lè)有問(wèn)題,請(qǐng)確定文件格式是否正確!", Toast.LENGTH_LONG)
					.show();
		}
	}

	// 編寫一個(gè)算法, 將傳入的毫秒數(shù)轉(zhuǎn)換成為 分鐘:秒鐘 的格式
	private String getTextByMs(int ms) {
		// 先轉(zhuǎn)換成秒
		int s = ms / 1000;
		// 計(jì)算分鐘
		int min = s / 60;
		// 計(jì)算剩余的秒數(shù)
		s = s % 60;
		// 拼接字符串,并補(bǔ)0
		StringBuilder builder = new StringBuilder();
		if (min < 10) {
			builder.append(0);
		}
		builder.append(min);
		builder.append(":");
		if (s < 10) {
			builder.append(0);
		}
		builder.append(s);

		return builder.toString();
	}

	@Override
	protected void onDestroy() {
		// 退出時(shí)釋放音樂(lè)
		if (player != null) {
			if (player.isPlaying()) {
				player.stop();
			}
			player.release();
		}
		if (t != null) {
			try {
				flag = false;
				t.interrupt();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		super.onDestroy();
	}
}


//注意,若是在執(zhí)行時(shí)沒(méi)有音樂(lè),或是sdcard讀取不出的話,可能是配置上出現(xiàn)問(wèn)題。

關(guān)于android通過(guò)SQLite數(shù)據(jù)庫(kù)的操作如何實(shí)現(xiàn)音樂(lè)播放器問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI