Android操作系统Music源码修改:把包名,各种命名都修改成自己的

 

 

修改Android操作系统Music源码,把后台播放核心服务对外暴漏:

<!-- 核心服务 -->
        <!--
            定义对外暴露的配置
            android:exported="true"
            android:process=":remote"
            android:enabled="true"
        -->
        <service android:name="liudeli.music2.service.MediaPlaybackService"
            android:exported="true"
            android:process=":remote"
            android:enabled="true">

            <intent-filter>

                <!--
                    定义对外暴露的 唯一标示
                 -->
                <action android:name="liudeli.custom.system.music.backplay.service" />

            </intent-filter>

        </service>

 

 阅读Android操作系统Music源码的AIDL:

// IMediaPlaybackService.aidl
package liudeli.music2.service;

// Declare any non-default types here with import statements

import android.graphics.Bitmap;

interface IMediaPlaybackService
{
    void openFile(String path);
    void open(in long [] list, int position);
    int getQueuePosition();
    boolean isPlaying();
    void stop();
    void pause();
    void play();
    void prev();
    void next();
    long duration();
    long position();
    long seek(long pos);
    String getTrackName();
    String getAlbumName();
    long getAlbumId();
    String getArtistName();
    long getArtistId();
    void enqueue(in long [] list, int action);
    long [] getQueue();
    void moveQueueItem(int from, int to);
    void setQueuePosition(int index);
    String getPath();
    long getAudioId();
    void setShuffleMode(int shufflemode);
    int getShuffleMode();
    int removeTracks(int first, int last);
    int removeTrack(long id);
    void setRepeatMode(int repeatmode);
    int getRepeatMode();
    int getMediaMountedCount();
    int getAudioSessionId();

    String getLyricPath();
    String getArtistPath();
}

 

阅读Android操作系统核心后台播放服务:

 

 

经过阅读Android操作系统Music源码发现,系统Music播放音乐采用来MediaPlaybackService服务来处理复杂的音乐播放逻辑,还用来AIDL来接口控制播放

既然如此,我就修改AndroidManifest.xml--->MediaPlaybackService服务,对外暴露,⚠️注意:暴露的时候,action:name="必须唯一"

 

 

-------------------- 以下代码是创建一个Android工程,来访问操作系统Music播放服务来播放音乐🎵

新创建的工程和操作系统Music工程的AIDL保存一致(包名 所以 都要一模一样):

 

绑定操心系统服务,并播放音乐🎵:

package liudeli.service1;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;

import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import liudeli.music2.service.IMediaPlaybackService;

public class PlaySystemMusicActivity extends Activity {

    private final String TAG = PlaySystemMusicActivity.class.getSimpleName();

    private TextView tvMusicStatue;

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

        // 绑定操作系统Music的服务
        Intent intent = new Intent();
        intent.setAction("liudeli.custom.system.music.backplay.service");
        intent.setPackage("liudeli.music2");
        bindService(intent, conn, BIND_AUTO_CREATE);
        alterShow("操作系统Music的服务绑定成功");

        tvMusicStatue = findViewById(R.id.tv_music_statue);
    }

    private IMediaPlaybackService iMediaPlaybackService;

    /**
     * 操作系统Music的服务接口
     */
    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 代理对象转换
            iMediaPlaybackService = IMediaPlaybackService.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    public void playMusic(View view) {
        if (null != iMediaPlaybackService) {
            try {
                String path = iMediaPlaybackService.getPath();
                iMediaPlaybackService.openFile(path);
                iMediaPlaybackService.play();
                Log.d(TAG, " path:" + path);

                /*iMediaPlaybackService.openFile(path);
                iMediaPlaybackService.play();*/

                updateMusicStatus();

            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }
    }

    public void pauseMusic(View view) {
        if (null != iMediaPlaybackService) {
            try{
                if (!iMediaPlaybackService.isPlaying()) {
                    alterShow("操作系统的Music还没有播放呢,还不能暂停哦");
                    return;
                }
                iMediaPlaybackService.pause();

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

    public void continueMusic(View view) {
        if (null != iMediaPlaybackService) {
            try{
                if (iMediaPlaybackService.isPlaying()) {
                    alterShow("操作系统的Music播放中,不能继续播放");
                    return;
                }
                iMediaPlaybackService.play();

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

    public void stopMusic(View view) {
        if (null != iMediaPlaybackService) {
            try{
                if (!iMediaPlaybackService.isPlaying()) {
                    alterShow("操作系统的Music还没有播放呢,还不能停止哦");
                    return;
                }
                iMediaPlaybackService.stop();

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

    public void prevMusic(View view) {
        if (null != iMediaPlaybackService) {
            try {
                iMediaPlaybackService.prev();

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public void nextMusic(View view) {
        if (null != iMediaPlaybackService) {
            try {
                iMediaPlaybackService.next();

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    public void test(View view) {
        if (null != iMediaPlaybackService) {
            try {
                long duration = iMediaPlaybackService.duration();
                long position = iMediaPlaybackService.position();

                /*iMediaPlaybackService.seek(position +=10);

                long[] queues = iMediaPlaybackService.getQueue();
                for (long queue : queues) {
                    Log.d(TAG, "queue:" + queue);
                }
                Random random = new Random(queues.length);
                iMediaPlaybackService.setQueuePosition(random.nextInt());*/

                String trackName = iMediaPlaybackService.getTrackName();
                String albumName = iMediaPlaybackService.getAlbumName();
                Log.d(TAG, "duration:" + duration
                        + " position:" + position
                        + " trackName:" + trackName
                        + " albumName:" + albumName);

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
        alterShow("操作系统Music的服务解绑成功");
    }

    private void alterShow(String text) {
        Toast.makeText(PlaySystemMusicActivity.this, text, Toast.LENGTH_LONG).show();
    }

    private synchronized void updateMusicStatus() throws RemoteException{
        long duration = iMediaPlaybackService.duration();
        long position = iMediaPlaybackService.position();
        String trackName = iMediaPlaybackService.getTrackName();
        String albumName = iMediaPlaybackService.getAlbumName();
        String aristName = iMediaPlaybackService.getArtistName();

        tvMusicStatue.setText("歌曲时长:" + timeParse(duration) +
                              " ,目前播放:" + timeParse(position) +
                              " ,歌曲:" + trackName +
                              " ,专辑:" + albumName +
                              " ,歌手:" + aristName);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            updateMusicStatus();
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        },1000);
    }

    /**
     * Android 音乐播放器应用里,读出的音乐时长为 long 类型以毫秒数为单位,
     * 例如:将 234736 转化为分钟和秒应为 03:55 (包含四舍五入)
     * @param duration 音乐时长
     * @return
     */
    public String timeParse(long duration) {
        String time = "" ;
        long minute = duration / 60000 ;
        long seconds = duration % 60000 ;
        long second = Math.round((float)seconds/1000) ;
        if( minute < 10 ){
            time += "0" ;
        }
        time += minute+":" ;
        if( second < 10 ){
            time += "0" ;
        }
        time += second ;
        return time ;
    }

}

 

Layout相关:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="播放操作系统Music中的音乐"
        android:onClick="playMusic"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="暂停操作系统Music中的音乐"
        android:onClick="pauseMusic"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="继续播放操作系统Music中的音乐"
        android:onClick="continueMusic"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止操作系统Music中的音乐"
        android:onClick="stopMusic"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="prevMusic"
            android:text="上一曲"
            />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="nextMusic"
            android:text="下一曲"
            />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="test"
            android:text="test"
            android:visibility="gone"
            />

    </LinearLayout>

    <TextView
        android:id="@+id/tv_music_statue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="还没有播放歌曲"/>

</LinearLayout>

 

完成✅去 bind 操作系统Music来播放音乐:

 

请看,我播放原生Android操作系统Music的图标:

 

请看,我调用Android操作系统Music后显示的图标:

 

 Android操作系统Music暂停后 图标消失

我的应用暂停后,图标也会消失,我完全是在使用Android操作系统Music里面的播放处理逻辑