MusicPlayer音乐播放器Android

【音频采集】
你可以使用手机进行现场录音,实现步骤如下:
第一步:在功能清单文件AndroidManifest.xml中添加音频刻录权限:
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
第二步:编写音频刻录代码:

MediaRecorder recorder = new MediaRecorder();recorder.setAudioSource(MediaRecorder.AudioSource.MIC);//从麦克风采集声音recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//内容输出格式recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//音频编码方式recorder.setOutputFile("/mnt/sdcard/glsite.amr");recorder.prepare();//预期准备recorder.start();   //开始刻录...recorder.stop();//停止刻录recorder.reset();   //重设recorder.release(); //刻录完成一定要释放资源

在Android开发中我们经常使用MediaPlayer来播放音频文件,但是MediaPlayer存在一些不足,例如:资源占用量较高、延迟时间较长、不支持多个音频同时播放等。这些缺点决定了MediaPlayer在某些场合的使用情况不会很理想,例如在对时间精准度要求相对较高的游戏开发中。 
   在游戏开发中我们经常需要播放一些游戏音效(比如:子弹爆炸,物体撞击等),这些音效的共同特点是短促、密集、延迟程度小。在这样的场景下,我们可以使用SoundPool代替MediaPlayer来播放这些音效。 
   SoundPool(android.media.SoundPool),顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、播放比率等参数,支持通过ID对多个音频流进行管理。
   就现在已知的资料来说,SoundPool有一些设计上的BUG,从固件版本1.0开始有些还没有修复,我们在使用中应该小心再小心。相信将来Google会修复这些问题,但我们最好还是列出来:
  1. SoundPool最大只能申请1M的内存空间,这就意味着我们只能用一些很短的声音片段,而不是用它来播放歌曲或者做游戏背景音乐。
  2. SoundPool提供了pause和stop方法,但这些方法建议最好不要轻易使用,因为有些时候它们可能会使你的程序莫名其妙的终止。建议使用这两个方法的时候尽可能多做测试工作,还有些朋友反映它们不会立即中止播放声音,而是把缓冲区里的数据播放完才会停下来,也许会多播放一秒钟。
  3. SoundPool的效率问题。其实SoundPool的效率在这些播放类中算是很好的了,但是有的朋友在G1中测试它还是有100ms左右的延迟,这可能会影响用户体验。也许这不能怪SoundPool本身,因为到了性能比较好的Droid中这个延迟就可以让人接受了。
  在现阶段SoundPool有这些缺陷,但也有着它不可替代的优点,基于这些我们建议大在如下情况中多使用SoundPool:1.应用程序中的声效(按键提示音,消息等)2.游戏中密集而短暂的声音(如多个飞船同时爆炸)

【SoundPool】
开发步骤:
1> 往项目的res/raw目录中放入音效文件。
2> 新建SoundPool对象,然后调用SoundPool.load()加载音效,调用SoundPool.play()方法播放指定音效文件。

public class AudioActivity extends Activity {
private SoundPool pool;
@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);//指定声音池的最大音频流数目为10,声音品质为5pool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);final int sourceid = pool.load(this, R.raw.pj, 0);//载入音频流,返回在池中的idButton button = (Button)this.findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {//播放音频,第二个参数为左声道音量;第三个参数为右声道音量;第四个参数为优先级;第五个参数为循环次数,0不循环,-1循环;第六个参数为速率,速率最低0.5最高为2,1代表正常速度pool.play(sourceid, 1, 1, 0, -1, 1);}});
}
}

demo:

1. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.glsite.musicplayer"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><applicationandroid: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"><serviceandroid:name=".MusicPlayerService"android:enabled="true"android:exported="true"></service><activity android:name=".SettingActivity" /><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>

2. MusicPlayer\app\src\main\res\menu\activity_main.xml  菜单

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><item android:id="@+id/item_setting"android:title="设置界面"/><item android:id="@+id/item_exit"android:title="关闭播放器"/>
</menu>

3.MusicPlayer\app\src\main\res\layout

3.1activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"><ListViewandroid:id="@+id/lv"android:layout_width="match_parent"android:layout_height="match_parent"></ListView></android.support.constraint.ConstraintLayout>

3.2 activity_setting.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".SettingActivity"android:orientation="vertical"><RadioGroupandroid:id="@+id/rg_mode"android:layout_width="wrap_content"android:layout_height="wrap_content" ><RadioButtonandroid:id="@+id/rb_cycle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="单曲循环" /><RadioButtonandroid:id="@+id/rb_next"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="播放下一曲" /><RadioButtonandroid:id="@+id/rb_stop"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_weight="1"android:text="播放后停止" /></RadioGroup>
</LinearLayout>

3.3 item_music.xml

<?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"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:id="@+id/tv_item_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:layout_marginTop="5dp"android:paddingTop="5dp"android:paddingBottom="5dp"android:text="歌曲名称"android:textColor="#99ff0000"android:textSize="20sp" /><ImageViewandroid:id="@+id/imageView"android:layout_width="25dp"android:layout_height="25dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="5dp"app:srcCompat="@mipmap/ic_launcher" /></RelativeLayout>

4.MusicPlayer\app\src\main\java\com\glsite\musicplayer

4.1BaseActivity 运行时权限

package com.glsite.musicplayer;import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;/*** @author Admin* @version $Rev$* @des ${TODO}* @updateAuthor $Author$* @updateDes ${TODO}*/
public class BaseActivity extends AppCompatActivity {//**************** Android M Permission (Android 6.0权限控制代码封装)private int permissionRequestCode = 88;private PermissionCallback permissionRunnable;public interface PermissionCallback {void hasPermission();void noPermission();}/*** Android M运行时权限请求封装** @param permissionDes 权限描述* @param runnable      请求权限回调* @param permissions   请求的权限(数组类型),直接从Manifest中读取相应的值,比如Manifest.permission.WRITE_CONTACTS*/public void performCodeWithPermission(@NonNull String permissionDes, PermissionCallback runnable, @NonNull String... permissions) {if (permissions == null || permissions.length == 0)return;//        this.permissionrequestCode = requestCode;this.permissionRunnable = runnable;if ((Build.VERSION.SDK_INT < Build.VERSION_CODES.M) || checkPermissionGranted(permissions)) {if (permissionRunnable != null) {permissionRunnable.hasPermission();permissionRunnable = null;}} else {//permission has not been granted.requestPermission(permissionDes, permissionRequestCode, permissions);}}private boolean checkPermissionGranted(String[] permissions) {boolean flag = true;for (String p : permissions) {if (ActivityCompat.checkSelfPermission(this, p) != PackageManager.PERMISSION_GRANTED) {flag = false;break;}}return flag;}private void requestPermission(String permissionDes, final int requestCode, final String[] permissions) {if (shouldShowRequestPermissionRationale(permissions)) {/*1. 第一次请求权限时,用户拒绝了,下一次:shouldShowRequestPermissionRationale()  返回 true,应该显示一些为什么需要这个权限的说明2.第二次请求权限时,用户拒绝了,并选择了“不在提醒”的选项时:shouldShowRequestPermissionRationale()  返回 false3. 设备的策略禁止当前应用获取这个权限的授权:shouldShowRequestPermissionRationale()  返回 false*/// Provide an additional rationale to the user if the permission was not granted// and the user would benefit from additional context for the use of the permission.// For example, if the request has been denied previously.//            Snackbar.make(getWindow().getDecorView(), requestName,//                    Snackbar.LENGTH_INDEFINITE)//                    .setAction(R.string.common_ok, new View.OnClickListener() {//                        @Override//                        public void onClick(View view) {//                            ActivityCompat.requestPermissions(BaseAppCompatActivity.this,//                                    permissions,//                                    requestCode);//                        }//                    })//                    .show();//如果用户之前拒绝过此权限,再提示一次准备授权相关权限new AlertDialog.Builder(this).setTitle("提示").setMessage(permissionDes).setPositiveButton("授权", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);}}).show();} else {// Contact permissions have not been granted yet. Request them directly.ActivityCompat.requestPermissions(BaseActivity.this, permissions, requestCode);}}private boolean shouldShowRequestPermissionRationale(String[] permissions) {boolean flag = false;for (String p : permissions) {if (ActivityCompat.shouldShowRequestPermissionRationale(this, p)) {flag = true;break;}}return flag;}/*** Callback received when a permissions request has been completed.*/@Overridepublic void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults) {if (requestCode == permissionRequestCode) {if (verifyPermissions(grantResults)) {if (permissionRunnable != null) {permissionRunnable.hasPermission();permissionRunnable = null;}} else {Toast.makeText(this, "暂无权限执行相关操作!", Toast.LENGTH_SHORT).show();if (permissionRunnable != null) {permissionRunnable.noPermission();permissionRunnable = null;}}} else {super.onRequestPermissionsResult(requestCode, permissions, grantResults);}}public boolean verifyPermissions(int[] grantResults) {// At least one result must be checked.if (grantResults.length < 1) {return false;}// Verify that each required permission has been granted, otherwise return false.for (int result : grantResults) {if (result != PackageManager.PERMISSION_GRANTED) {return false;}}return true;}//********************** END Android M Permission ****************************************
}

4.2MainActivity.java

package com.glsite.musicplayer;import android.Manifest;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Environment;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;import java.io.File;
import java.util.ArrayList;public class MainActivity extends BaseActivity {private ListView mLv;private IMusicService mIMusicService;public static final String MP3DIR = Environment.getExternalStorageDirectory() + "/Download/";private ArrayList<String> mMp3List;private MyConn mConn;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mLv = findViewById(R.id.lv);performCodeWithPermission("读取SD卡需要用到的权限", new PermissionCallback() {@Overridepublic void hasPermission() {initPlayList();}@Overridepublic void noPermission() {}}, Manifest.permission.READ_EXTERNAL_STORAGE);Intent intent = new Intent(this, MusicPlayerService.class);startService(intent);mConn = new MyConn();bindService(intent, mConn, BIND_AUTO_CREATE);mLv.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {if (mIMusicService != null) {mIMusicService.callPlay(mMp3List, position);} else {Toast.makeText(MainActivity.this,"还没有绑定服务吧", Toast.LENGTH_SHORT).show();}}});}private class MyConn implements ServiceConnection {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mIMusicService = (IMusicService) service;}@Overridepublic void onServiceDisconnected(ComponentName name) {}}/*** 初始化播放列表*/private void initPlayList() {File file = new File(MP3DIR);File[] files = file.listFiles();mMp3List = new ArrayList<>();for (File f  : files) {if (f.getName().endsWith(".mp3")) {mMp3List.add(f.getAbsolutePath());System.out.println(f.getAbsolutePath());}}mLv.setAdapter(new MusicListAdapter());}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {MenuInflater inflater = new MenuInflater(this);inflater.inflate(R.menu.activity_main, menu);return super.onCreateOptionsMenu(menu);}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {if (item.getItemId() == R.id.item_setting) {// 启动一个设置界面Intent intent = new Intent(this, SettingActivity.class);startActivity(intent);} else if (item.getItemId() == R.id.item_exit){// 停止播放并且退出playerExit();}return super.onOptionsItemSelected(item);}/*** 停止播放并退出*/private void playerExit() {if (mIMusicService != null) {mIMusicService.callStop();}if (mConn != null) {unbindService(mConn);mConn = null;}Intent intent = new Intent(this, MusicPlayerService.class);stopService(intent);finish();}@Overrideprotected void onDestroy() {playerExit();super.onDestroy();}private class MusicListAdapter extends BaseAdapter {@Overridepublic int getCount() {return mMp3List.size();}@Overridepublic Object getItem(int position) {return mMp3List.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {View view = View.inflate(MainActivity.this, R.layout.item_music, null);TextView tv_name = (TextView) view.findViewById(R.id.tv_item_name);String path = mMp3List.get(position);tv_name.setText(path.substring(path.lastIndexOf("/") + 1));return view;}}
}

4.3IMusicService.java

package com.glsite.musicplayer;import java.util.List;/*** @author glsite.com* @version $Rev$* @des ${TODO}* @updateAuthor $Author$* @updateDes ${TODO}*/
public interface IMusicService {/*** 调用服务里面的播放逻辑** @param playList*          音乐资源的路径集合* @param position*/public void callPlay(List<String> playList, int position);/*** 调用停止播放的方法*/public void callStop();}

4.4MusicPlayerService 音乐服务

package com.glsite.musicplayer;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;import java.io.IOException;
import java.util.List;public class MusicPlayerService extends Service {public static final int MUSIC_STOP = 0;public static final int MUSIC_PLAYING = 1;public static final int MUSIC_PAUSE = 2;private SharedPreferences mSp;private MediaPlayer mMediaPlayer;public static int playingStatus = 0;public MusicPlayerService() {}@Overridepublic IBinder onBind(Intent intent) {return new MyBinder();}@Overridepublic void onCreate() {System.out.println("音乐播放器服务开启了");mSp = getSharedPreferences("config", MODE_PRIVATE);mMediaPlayer = new MediaPlayer();super.onCreate();}@Overridepublic void onDestroy() {System.out.println("音乐播放服务关闭了");super.onDestroy();}private class MyBinder extends Binder implements IMusicService {@Overridepublic void callPlay(List<String> playList, int position) {play(playList, position);}@Overridepublic void callStop() {stopPlayer();}}/*** 停止播放*/private void stopPlayer() {if (mMediaPlayer != null) {mMediaPlayer.stop();mMediaPlayer.release();mMediaPlayer = null;}NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);nm.cancelAll();}/*** 播放音乐** @param playList*          所有音频列表* @param position*          当前的位置*/private void play(final List<String> playList, final int position) {try {if (mMediaPlayer.isPlaying()) {mMediaPlayer.stop();}mMediaPlayer.reset();mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);System.out.println(playList.get(position));mMediaPlayer.setDataSource(playList.get(position));mMediaPlayer.prepare();mMediaPlayer.start();String path = playList.get(position);System.out.println(path.substring(path.lastIndexOf("/") + 1));showNotification(path.substring(path.lastIndexOf("/") + 1));mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {int mode = mSp.getInt("mode", 0);if (mode == SettingActivity.CYCLE) {play(playList, position);} else if (mode == SettingActivity.NEXT){// 播放下一曲int newPosition = position + 1;if (newPosition >= playList.size()) {newPosition = 0;}play(playList, newPosition);} else if (mode == SettingActivity.STOP) {// 设置状态为停止playingStatus = MUSIC_STOP;}}});} catch (Exception e) {e.printStackTrace();playingStatus = MUSIC_STOP;}}/*** 显示播放音乐的通知提醒** @param filename*          音乐名*/private void showNotification(String filename) {// 判断如果当前的SDK版本>=8.0if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {String id = "channel_1";int importance = NotificationManager.IMPORTANCE_LOW;NotificationChannel channel = new NotificationChannel(id, "123", importance);Notification noti = new Notification.Builder(this, id).setContentTitle("酷狗音乐正在播放").setContentText(filename).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).build();NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);nm.createNotificationChannel(channel);nm.notify(1, noti);// 添加channel} else {// 如果当前的SDK版本<8.0Notification noti = new Notification.Builder(this).setContentTitle("酷狗音乐正在播放").setContentText(filename).setSmallIcon(R.mipmap.ic_launcher).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)).build();NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);nm.notify(1, noti);}}}

4.5SettingActivity.java

package com.glsite.musicplayer;import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.RadioButton;
import android.widget.RadioGroup;public class SettingActivity extends AppCompatActivity {public static final int CYCLE = 1;public static final int NEXT = 2;public static final int STOP = 3;private RadioGroup mRgMode;private SharedPreferences mSp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_setting);mRgMode = findViewById(R.id.rg_mode);mSp = getSharedPreferences("config", MODE_PRIVATE);int mode = mSp.getInt("mode", 0);RadioButton rb;switch (mode) {case CYCLE:rb = findViewById(R.id.rb_cycle);rb.setChecked(true);break;case NEXT:rb = findViewById(R.id.rb_next);rb.setChecked(true);break;case STOP:rb = findViewById(R.id.rb_stop);rb.setChecked(true);break;default:break;}mRgMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {SharedPreferences.Editor editor = mSp.edit();switch (checkedId) {case R.id.rb_cycle:editor.putInt("mode", CYCLE);break;case R.id.rb_next:editor.putInt("mode", NEXT);break;case R.id.rb_stop:editor.putInt("mode", STOP);break;default:break;}editor.commit();}});}
}

MusicPlayer音乐播放器Android相关推荐

  1. android 带记忆功能的播放器源码,【全开源可二开】带后台管理面板的在线音乐播放器Android应用APP源码...

    这是一款带后台管理面板的在线音乐播放器Android应用APP源码,可让您更快地构建在线和离线android音频播放器,代码全开源适合二次开发.该源码自带2个紫色和橙色主题(允许您添加更多主题),多语 ...

  2. android MusicPlayer 音乐播放器 Lrc歌词控件的实现

    MusicPlayer Lrc歌词控件的实现 最近在做一个音乐播放器,关于其中歌词控件,上网查过了一些资料,然后进行修改,也算完整的实现了其功能.先看看实现后的效果. 实现的原理实际上是自定义一个Vi ...

  3. 音乐播放器android版,Android版音乐播放器

    音乐播放器是一个非常常见的应用,这篇博客就是介绍如何制作一个简单的音乐播放器,这款音乐播放器具有以下的功能:播放歌曲.暂停播放歌曲..显示歌曲的总时长.显示歌曲的当前播放时长.调节滑块可以将歌曲调节到 ...

  4. android 系统锁屏音乐播放器,Android实现音乐播放器锁屏页

    本文实例为大家分享了Android音乐播放器锁屏页的具体代码,供大家参考,具体内容如下 首页我们先看一下效果图 下边来说一下实现逻辑,其主要思路就是新建一个activity使其覆盖在锁屏页上边. 一. ...

  5. android 锁屏显示音乐播放器,Android锁屏界面控制音乐播放

    目前,在锁屏界面控制音乐播放有两种常用方式. 第一种方式:原生Android系统及自带音乐播放器. 锁屏界面端: 原生Android中,锁屏界面相关的UI由KeyguardHostView提供,Key ...

  6. 轻量级音乐播放器 android,5款顶级Android离线音乐播放器,哪款才是你的菜?

    打开左侧栏,Stellio 的功能排列井井有条.你可以选择多样的播放队列,根据专辑.演奏者等属性快速找到想要的歌曲. 重视细节的Stellio 还有睡眠模式.自定义widget 等小功能.难能可贵的是 ...

  7. android仿音乐播放器,Android仿音乐播放器功能

    本文实例为大家分享了Android仿音乐播放器功能的具体代码,供大家参考,具体内容如下 读取本地音乐文件 源代码: import android.media.MediaPlayer; import a ...

  8. android开发音乐播放器,Android开发简易音乐播放器

    这里介绍一个简易的音乐播放器,供大家参考,具体内容如下 效果图如下: 但是,由于这是一个简易版的音乐播放器,所播放的音乐只有一首,且被写死,但,操作却十分简单,方便理解! 这是代码的主要设计: 音乐主 ...

  9. 音乐播放器-Android+okhttp连接+Spring boot服务器+oracle数据库+腾讯云端

    1.整体架构 1.1软件系统架构: Android+okhttp连接+Spring boot服务器+oracle数据库+腾讯云端服务器地址:https://github.com/DNFDS/Twink ...

最新文章

  1. [CF1066C]Books Queries
  2. hibernate.jdbc.fetch_size 和 hibernate.jdbc.batch_size
  3. [转]MyBatis中resultType与resultMap区别
  4. javascript--弹出对话框 四种对话框 获得用户输入值 .
  5. python里的关键字有哪些_Python 中的关键字有哪些?
  6. MAC 下用GCC编译报错:“Undefined symbols for architecture x86_64: ”
  7. 华中数控hnc一818b_数控车床精确对刀方法总结
  8. 数值分析书籍以及Intel性能分析工具
  9. javascript---淡入淡出的效果轮换转播后续
  10. 如何提升会员列表数据的质量
  11. dll依赖查看工具-depends
  12. 体制内名校生和普校生发展有无差别?看懂这3个潜规则,越混越好
  13. 计算机应用与基础app,手机APP支持下《计算机应用基础》课程探究性学习活动设计与实验研究...
  14. html颜色代码错误,HTML颜色代码表
  15. web登录实现带php
  16. 亚马逊云科技又一全球人才培养项目在中国的落地
  17. uniapp之地址定位选择,根据字母排序
  18. SQL 数据库 学习 011 关系、一对一、一对多、多对多
  19. IIS 6 UrlRewrite 步骤
  20. 一个公众号绑定多个商户支付

热门文章

  1. 关闭VMware声音
  2. 最经典的权限设计同样也是最糟糕的权限设计,权限设计理念最关键第一步之间的PK...
  3. 事务是什么?事务的4个特点(ACID),事务的开启与结束
  4. python全栈开发-Day11 迭代器、生成器、面向过程编程
  5. Linux的重要子目录
  6. ecshop 多语言版 fckeditor,支持中文英文韩文等众多语言
  7. Activity的四种启动模式区别
  8. domino Format函数详解
  9. 使用SVN+apache搭建一个版本控制服务器
  10. zabbix配置微信报警