Search code examples
androidandroid-intentandroid-manifestandroid-mediaplayerintentfilter

Set my music player as default music player


I'm trying to give the possibility to set my app as default music player, but i found two problems.

The first one is about the manifst declaration: According to Google music app Manifest (manifest) the code to put on my selected activity is:

    <activity
        android:name=".Dashboard"
        android:theme="@style/NoActionBar"
        android:screenOrientation="portrait"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="content"/>
            <data android:host="media"/>
            <data android:mimeType="audio/*"/>
            <data android:mimeType="application/ogg"/>
            <data android:mimeType="application/x-ogg"/>
            <data android:mimeType="application/itunes"/>
        </intent-filter>
    </activity>

But if I try to open a music file, my application isn't in the list of compatible apps (why?). So I tried specyfing the file extension, in this way:

   <activity
        android:name=".Dashboard"
        android:theme="@style/NoActionBar"
        android:screenOrientation="portrait"
        android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="content"/>
            <data android:scheme="file" />
            <data android:mimeType="*/*" />
            <data android:pathPattern=".*\\.mp3" />
            <data android:host="*" />
        </intent-filter>
    </activity>

This code is working for me, but i think is not the best way. There is another activity with some important content-filter, and i don't know if it is the problem. It is the first activity (so the launching one, a login activity). his maifest declaration is

    <activity
        android:name=".LoginActivity"
        android:label="@string/app_name"
        android:theme="@style/NoActionBar"
        android:screenOrientation="portrait">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <action android:name="android.intent.action.MUSIC_PLAYER" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.LAUNCHER" />
            <category android:name="android.intent.category.APP_MUSIC" />
            <action android:name="android.intent.action.VIEW" />
        </intent-filter>
    </activity>

In this moment I can set my app as default when a .mp3 file is launched, but here the second problem: I can't intercept the Uri from Intent when the my app is on background. I tried to put getIntent().getData() on OnCreate, OnResume and OnStart, but the Data is always null when the music file is cliked and my app is on background. While it is non null when my app is not in background. Where/What have I to do to solve?


Solution

  • I can now answer to my own question. Thanks to CommonsWare comments and thanks to his old answer to another question:

    About the manifest this lines worked good for me, just change my actual intent-filter with:

    <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="file"/>
            <data android:mimeType="audio/*"/>
            <data android:mimeType="application/ogg"/>
            <data android:mimeType="application/x-ogg"/>
            <data android:mimeType="application/itunes"/>
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="http" />
            <data android:mimeType="audio/*"/>
            <data android:mimeType="application/ogg"/>
            <data android:mimeType="application/x-ogg"/>
            <data android:mimeType="application/itunes"/>
        </intent-filter>
        <intent-filter
            android:priority="-1">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="content" />
            <data android:mimeType="audio/*"/>
            <data android:mimeType="application/ogg"/>
            <data android:mimeType="application/x-ogg"/>
            <data android:mimeType="application/itunes"/>
        </intent-filter>
    

    About the non intercepted Data when app is on Background, I Solved in this way:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /*...*/
        interceptExternalIntentAndPlaySongFromUri(getIntent());
    }
    
    @Override
    protected void onNewIntent(Intent intent) {
        interceptExternalIntentAndPlaySongFromUri(intent);
    }
    
    private boolean interceptExternalIntentAndPlaySongFromUri(Intent intent){
        Uri data = intent.getData();
        if (data != null && intent.getAction() != null && 
    intent.getAction().equals(Intent.ACTION_VIEW)){      
            String scheme = data.getScheme();
            String filename = "";
            if ("file".equals(scheme)) {
                filename = data.getPath();
            } else {
                filename = data.toString();
            }
            player.setDataSource(filename);
            setIntent(new Intent());        //this is to remove the last intent 
    //without the above line, last request is reloaded when the user open another app 
    //and return in this
            return true;        //has intercepted an external intent
        }
        return false;           //has not intent to intercept
    }
    

    Thanks still @CommonsWare.