MusicPlayer音乐播放器Android

55 篇文章 1 订阅

                    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,声音品质为5
    pool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
    final int sourceid = pool.load(this, R.raw.pj, 0);//载入音频流,返回在池中的id
    Button 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" />

    <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">
        <service
            android: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">

    <ListView
        android: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">


    <RadioGroup
        android:id="@+id/rg_mode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <RadioButton
            android:id="@+id/rb_cycle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="单曲循环" />

        <RadioButton
            android:id="@+id/rb_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="播放下一曲" />

        <RadioButton
            android: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">

    <TextView
        android: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" />

    <ImageView
    android: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()  返回 false
            3. 设备的策略禁止当前应用获取这个权限的授权: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() {
                        @Override
                        public 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.
     */
    @Override
    public 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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLv = findViewById(R.id.lv);
        performCodeWithPermission("读取SD卡需要用到的权限", new PermissionCallback() {
            @Override
            public void hasPermission() {
                initPlayList();
            }

            @Override
            public 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() {
            @Override
            public 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 {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIMusicService = (IMusicService) service;
        }

        @Override
        public 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());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = new MenuInflater(this);
        inflater.inflate(R.menu.activity_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public 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();
    }

    @Override
    protected void onDestroy() {
        playerExit();
        super.onDestroy();
    }

    private class MusicListAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            return mMp3List.size();
        }

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

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

        @Override
        public 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() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    @Override
    public void onCreate() {
        System.out.println("音乐播放器服务开启了");
        mSp = getSharedPreferences("config", MODE_PRIVATE);
        mMediaPlayer = new MediaPlayer();
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        System.out.println("音乐播放服务关闭了");
        super.onDestroy();
    }

    private class MyBinder extends Binder implements IMusicService {

        @Override
        public void callPlay(List<String> playList, int position) {
            play(playList, position);
        }

        @Override
        public 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() {
                @Override
                public 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.0
        if (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.0
            Notification 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;

    @Override
    protected 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() {
            @Override
            public 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();
            }
        });
    }
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_无往而不胜_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值