lovegaoshi / react-native-track-player

A fully fledged audio module created for music apps. Provides audio playback, external media controls, chromecast support, background mode and more!
https://react-native-track-player.js.org/
Apache License 2.0
7 stars 12 forks source link

[feat] Android Auto #4

Closed lovegaoshi closed 1 month ago

lovegaoshi commented 1 year ago

=======

the app did not appear in the auto screen or lens picker when we attempted to test functionality. (???) for example, your app does not contain an intent filter for action 'android.media.action.MEDIA_PLAY_FROM_SERACH'.

https://stackoverflow.com/questions/53883825/cant-get-voice-commands-on-android-auto-media-app-work


   @Override
    public void onCreate() {
        super.onCreate();
        audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
        mSession = new MediaSessionCompat(this, "RService");
        mSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
                | MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS);
        mSession.setCallback(mCallback);
        mSessionConnector = new MediaSessionConnector(mSession);
        setSessionToken(mSession.getSessionToken());
        setMediaBrowser();
        initializeReceiver();
        C_F_App.createNotificationChannelPlayer(getApplicationContext());
        rNController = new RadioNotificationController(this, mSession, getApplicationContext());
    }

final MediaSessionCompat.Callback mCallback =
            new MediaSessionCompat.Callback() {
                @Override
                public void onPlayFromMediaId(String mediaId, Bundle extras) {
                    playForAuto(mediaId);
                }

                @Override
                public void onPlayFromSearch(String query, Bundle extras) {
                    super.onPlayFromSearch(query, extras);
                    Log.d("Test", "Test");
                }

                @Override
                public void onStop() {
                    playPause();
                }

                @Override
                public void onPlay() {
                    playPause();
                }

                @Override
                public void onPause() {
                    playPause();
                }
            };

public void setMediaBrowser() {
    mediaBrowser = new MediaBrowserCompat(getApplicationContext(),
            new ComponentName(getApplicationContext(), this.getClass()),
            new MediaBrowserCompat.ConnectionCallback() {
                @Override
                public void onConnected() {
                    super.onConnected();
                }

                @Override
                public void onConnectionSuspended() {
                    super.onConnectionSuspended();
                }

                @Override
                public void onConnectionFailed() {
                    super.onConnectionFailed();
                }
            }, null);

    mediaBrowser.connect();
}

@Override
public long getSupportedPrepareActions() {
    return PlaybackStateCompat.ACTION_PREPARE_FROM_MEDIA_ID |
            PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID |
            PlaybackStateCompat.ACTION_PREPARE_FROM_SEARCH |
            PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH;
}

=======

onLoadChilren: try with

        val mediaItems = listOf<MediaBrowserCompat.MediaItem>(MediaItem(
            MediaDescriptionCompat.Builder().setMediaId("myMediaId").setTitle("MyMedia").setSubtitle("MyMediaSubTitle").build(), MediaItem.FLAG_PLAYABLE
        ))

the mediaID is handled by onPlayFromMediaId see above. For AzusaPlayerMobile maybe set this to playlist-id-cid?

lovegaoshi commented 1 year ago

make sure to override


                @Override
                public void onStop() {
                    playPause();
                }

                @Override
                public void onPlay() {
                    playPause();
                }

                @Override
                public void onPause() {
                    playPause();
                }

in mediaSession.Callback. is this it thoguh?

lovegaoshi commented 1 year ago

ALL relevant methods in mediaSession.Callback must be overwritten, as in https://github.com/doublesymmetry/KotlinAudio/commit/06f0f41e2713b5bc370fa2b77178bbf5aa9f2ff2

see below for building tabs, i think. https://developer.android.com/training/cars/media#root-menu-structure

how to get sending data from RN to native to build mediaTree to work?

lovegaoshi commented 1 year ago

maybe https://developer.android.com/training/cars/media#apply_content_style and https://developer.android.com/training/cars/media#display_search and https://developer.android.com/training/cars/media#build_hierarchy should be implemented? i dont really need it

lovegaoshi commented 1 year ago

https://stackoverflow.com/questions/44354261/android-auto-communication-between-background-service-and-activity

i dont understand

Thus the answer was to take all of the app's playback-related code out of the Activity, move it into a background Service, and provide an API for passing on the relevant commands (and receiving data, state updates and so on) either from/to the foreground Activity (if/when the user is interacting with the app's UI) or from/to the MediaBrowserService (if/when the user is interacting through Android Auto's UI). Starting the service is something that can be easily done from either context, if/when needed.

right now if APM is closed and APM is "opened" in AA, either a circularProgress shows or nothing at all; AA's playback player is all empty.

I'm thinking since deeplink can be used to wake the app up, why dont I do the same when onBind is called. Then APM will be brought up to the front, player gets set up, all is good. Sure AIMP can do this without bringing AIMP to the foreground, but i dont think its an issue for APM. will just call feature intended.

======================

i spent too much time with the dumb print statement debug way to find out, for whatever reason onCreate overrides when called from AA only work in HeadlessJsMediaService, not in MusicService, not even when MusicService extends MediaBrowserServiceCompat. I guess just sending a deeplink from HeadlessJsMediaService at onCreate will just work?

---------------------------- PROCESS STARTED (13506) for package com.example ---------------------------- 2023-07-27 21:29:10.219 13506-13506 GVA-RNTP com.example D RNTP musicservice created. 2023-07-27 21:29:10.219 13506-13506 RNTP com.example D HEADLESSMEDIAJS CREATE CATCH 2023-07-27 21:29:10.220 13506-13506 RNTP com.example D HEADLESSMEDIAJS CREATE 2 2023-07-27 21:29:10.669 13506-13506 GVA-RNTP com.example D RNTP received loadChildren req: / ---------------------------- PROCESS ENDED (13506) for package com.example ---------------------------- ---------------------------- PROCESS STARTED (14313) for package com.example ---------------------------- 2023-07-27 21:29:19.902 14313-14313 RNTP com.example D HEADLESSMEDIAJS CREATE CATCH 2023-07-27 21:29:19.903 14313-14313 RNTP com.example D HEADLESSMEDIAJS CREATE 2

lovegaoshi commented 1 year ago

useful https://github.com/googlesamples/android-media-controller