Skip to content

Commit 8b9c6d4

Browse files
committed
Add a new way to pass data into the app via adb.
Originally there was only a set of extras that could be specified on the command line to set the package name, media browser component, and pass in a URI, search, or media ID. I've updated it to allow passing in the package name and a query that the developer may want to execute, and I've done it via a 'deep link' type of structure. I hope this will make it relatively easy for developers to use, and won't require using very short names for extras, which is typically not recommended best practice. If developers require the ability to pass in complex URIs (with multiple parameters) then they can fall back to an updated set of extras that follow recommended best practices in their naming. Change-Id: Ic6df65e9350d430e7fd9204ad4c458b117b1a300
1 parent dba3acf commit 8b9c6d4

File tree

5 files changed

+152
-14
lines changed

5 files changed

+152
-14
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,34 @@ Usage
2929
background, if provided.
3030
5. Press ```back``` to return to the list of media apps.
3131

32+
Via ADB
33+
-------
34+
35+
It's also possible to launch the app via ADB and the Activity manager (am).
36+
37+
Usage: ```adb shell am start mediacontroller://?[search|id|uri=]```
38+
39+
For example, to set up to play "Awakening" by _Silent Partner_ in UAMP, the following command
40+
could be used:
41+
42+
```adb shell am start "mediacontroller://com.example.android.uamp?id=__BY_GENRE__/Rock\|-1679589699"```
43+
44+
Alternatively, it's possible to use extras to pass parameters, which is recommended when passing
45+
parameters that include URI-like components:
46+
47+
Extra names:
48+
49+
- Package name : ```com.example.android.mediacontroller.PACKAGE_NAME```
50+
- Search term : ```com.example.android.mediacontroller.SEARCH```
51+
- Media ID : ```com.example.android.mediacontroller.MEDIA_ID```
52+
- URI : ```com.example.android.mediacontroller.URI```
53+
54+
Another example with UAMP is to perform a search with the term "jazz?" one would use:
55+
56+
```adb shell am start -n com.example.android.mediacontroller/.MediaAppControllerActivity --es com.example.android.mediacontroller.PACKAGE_NAME "com.example.android.uamp" --es com.example.android.mediacontroller.SEARCH "jazz?"```
3257

3358
Screenshots
34-
-----------
59+
===========
3560

3661
![](screenshots/screenshots.png "Controls, URIs, Playback")
3762

mediacontroller/src/main/AndroidManifest.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,18 @@
3434

3535
<activity
3636
android:name=".MediaAppControllerActivity"
37-
android:launchMode="singleTask" />
37+
android:launchMode="singleTask">
38+
39+
<intent-filter>
40+
<action android:name="android.intent.action.VIEW" />
41+
42+
<category android:name="android.intent.category.DEFAULT"/>
43+
<category android:name="android.intent.category.BROWSABLE"/>
44+
45+
<data
46+
android:scheme="mediacontroller" />
47+
intent-filter>
48+
activity>
3849

3950
application>
4051

mediacontroller/src/main/java/com/example/android/mediacontroller/LaunchActivity.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.os.AsyncTask;
2424
import android.os.Bundle;
2525
import android.support.annotation.NonNull;
26+
import android.support.v4.media.MediaBrowserServiceCompat;
2627
import android.support.v7.app.AppCompatActivity;
2728
import android.support.v7.util.DiffUtil;
2829
import android.support.v7.widget.LinearLayoutManager;
@@ -44,7 +45,6 @@
4445
* (via a receiver that responds to the action "android.media.browse.MediaBrowserService").
4546
*/
4647
public class LaunchActivity extends AppCompatActivity {
47-
4848
/**
4949
* Callback used by {@link FindMediaAppsTask}.
5050
*/
@@ -116,9 +116,6 @@ protected void onStart() {
116116
}
117117

118118
private class FindMediaAppsTask extends AsyncTask<Void, Void, List<MediaAppDetails>> {
119-
private static final String MEDIA_BROWSER_ACTION =
120-
"android.media.browse.MediaBrowserService";
121-
122119
private final AppListUpdatedCallback mCallback;
123120

124121
private FindMediaAppsTask(@NonNull AppListUpdatedCallback callback) {
@@ -140,7 +137,8 @@ protected List doInBackground(Void... params) {
140137
// Build an Intent that only has the MediaBrowserService action and query
141138
// the PackageManager for apps that have services registered that can
142139
// receive it.
143-
final Intent mediaBrowserIntent = new Intent(MEDIA_BROWSER_ACTION);
140+
final Intent mediaBrowserIntent =
141+
new Intent(MediaBrowserServiceCompat.SERVICE_INTERFACE);
144142
final List<ResolveInfo> services =
145143
packageManager.queryIntentServices(mediaBrowserIntent,
146144
PackageManager.GET_RESOLVED_FILTER);

mediacontroller/src/main/java/com/example/android/mediacontroller/MediaAppControllerActivity.java

Lines changed: 110 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,23 @@
1616
package com.example.android.mediacontroller;
1717

1818
import android.app.Activity;
19+
import android.content.ComponentName;
1920
import android.content.Context;
2021
import android.content.Intent;
22+
import android.content.pm.PackageManager;
23+
import android.content.pm.ResolveInfo;
2124
import android.graphics.Bitmap;
2225
import android.graphics.drawable.BitmapDrawable;
26+
import android.graphics.drawable.Drawable;
27+
import android.net.Uri;
2328
import android.os.Bundle;
2429
import android.os.RemoteException;
2530
import android.support.annotation.Nullable;
2631
import android.support.annotation.StringRes;
2732
import android.support.design.widget.Snackbar;
2833
import android.support.design.widget.TabLayout;
2934
import android.support.v4.media.MediaBrowserCompat;
35+
import android.support.v4.media.MediaBrowserServiceCompat;
3036
import android.support.v4.media.MediaMetadataCompat;
3137
import android.support.v4.media.session.MediaControllerCompat;
3238
import android.support.v4.media.session.PlaybackStateCompat;
@@ -37,17 +43,18 @@
3743
import android.support.v7.widget.Toolbar;
3844
import android.text.TextUtils;
3945
import android.util.Log;
40-
import android.util.SparseArray;
4146
import android.view.View;
4247
import android.view.ViewGroup;
4348
import android.widget.EditText;
4449
import android.widget.ImageView;
4550
import android.widget.Spinner;
4651
import android.widget.TextView;
52+
import android.widget.Toast;
4753

4854
import java.util.HashMap;
4955
import java.util.List;
5056
import java.util.Map;
57+
import java.util.Set;
5158

5259
/**
5360
* This class connects to a {@link android.support.v4.media.MediaBrowserServiceCompat}
@@ -68,10 +75,30 @@ public class MediaAppControllerActivity extends AppCompatActivity {
6875
private static final String STATE_URI_KEY =
6976
"com.example.android.mediacontroller.STATE_URI_KEY";
7077

78+
// Key names for external extras.
79+
private static final String PACKAGE_NAME_EXTRA =
80+
"com.example.android.mediacontroller.PACKAGE_NAME";
81+
private static final String SEARCH_EXTRA = "com.example.android.mediacontroller.SEARCH";
82+
private static final String URI_EXTRA ="com.example.android.mediacontroller.URI";
83+
private static final String MEDIA_ID_EXTRA = "com.example.android.mediacontroller.MEDIA_ID";
84+
85+
// Hint to use the currently loaded app rather than specifying a package.
86+
private static final String CURRENT_PACKAGE = "current";
87+
88+
// Parameters for deep link URI.
89+
private static final String SEARCH_PARAM = "search";
90+
private static final String MEDIA_ID_PARAM = "id";
91+
private static final String URI_PARAM = "uri";
92+
7193
// Key name for Intent extras.
7294
private static final String APP_DETAILS_EXTRA =
7395
"com.example.android.mediacontroller.APP_DETAILS_EXTRA";
7496

97+
// Index values for spinner.
98+
private static final int SEARCH_INDEX = 0;
99+
private static final int MEDIA_ID_INDEX = 1;
100+
private static final int URI_INDEX = 2;
101+
75102
private MediaAppDetails mMediaAppDetails;
76103
private MediaControllerCompat mController;
77104
private MediaBrowserCompat mBrowser;
@@ -94,7 +121,7 @@ public class MediaAppControllerActivity extends AppCompatActivity {
94121
* @return An Intent that can be used to start the Activity.
95122
*/
96123
public static Intent buildIntent(final Activity activity,
97-
final MediaAppDetails appDetails) {
124+
final MediaAppDetails appDetails) {
98125
final Intent intent = new Intent(activity, MediaAppControllerActivity.class);
99126
intent.putExtra(APP_DETAILS_EXTRA, appDetails);
100127
return intent;
@@ -172,14 +199,65 @@ private void handleIntent(Intent intent) {
172199
return;
173200
}
174201

175-
if (intent.getData() != null) {
176-
String uri = intent.getData().toString();
177-
mUriInput.setText(uri);
202+
final Uri data = intent.getData();
203+
final String appPackageName;
204+
if (data != null) {
205+
appPackageName = data.getHost();
206+
207+
final Set<String> params = data.getQueryParameterNames();
208+
if (params.contains(SEARCH_PARAM)) {
209+
mInputTypeView.setSelection(SEARCH_INDEX);
210+
mUriInput.setText(data.getQueryParameter(SEARCH_PARAM));
211+
} else if (params.contains(MEDIA_ID_PARAM)) {
212+
mInputTypeView.setSelection(MEDIA_ID_INDEX);
213+
mUriInput.setText(data.getQueryParameter(MEDIA_ID_PARAM));
214+
} else if (params.contains(URI_PARAM)) {
215+
mInputTypeView.setSelection(URI_INDEX);
216+
mUriInput.setText(data.getQueryParameter(URI_PARAM));
217+
}
218+
} else if (intent.hasExtra(PACKAGE_NAME_EXTRA)) {
219+
appPackageName = intent.getStringExtra(PACKAGE_NAME_EXTRA);
220+
} else {
221+
appPackageName = null;
222+
}
223+
224+
// Create app details from URI, if one was present.
225+
if (appPackageName != null) {
226+
if (mMediaAppDetails == null || !appPackageName.equals(CURRENT_PACKAGE)) {
227+
final MediaAppDetails appDetails = buildMediaDetailsFromPackage(appPackageName);
228+
229+
if (appDetails == null) {
230+
// Couldn't build the media app details so alert the user and exit.
231+
Toast.makeText(this,
232+
getString(R.string.no_app_for_package, appPackageName),
233+
Toast.LENGTH_LONG)
234+
.show();
235+
finish();
236+
return;
237+
} else {
238+
mMediaAppDetails = appDetails;
239+
}
240+
}
178241
}
179242

180243
final Bundle extras = intent.getExtras();
181-
if (extras != null && extras.containsKey(APP_DETAILS_EXTRA)) {
182-
mMediaAppDetails = extras.getParcelable(APP_DETAILS_EXTRA);
244+
if (extras != null) {
245+
// Pull data out of the extras, if they're there.
246+
if (extras.containsKey(SEARCH_EXTRA)) {
247+
mInputTypeView.setSelection(SEARCH_INDEX);
248+
mUriInput.setText(extras.getString(SEARCH_EXTRA));
249+
} else if (extras.containsKey(MEDIA_ID_EXTRA)) {
250+
mInputTypeView.setSelection(MEDIA_ID_INDEX);
251+
mUriInput.setText(extras.getString(MEDIA_ID_EXTRA));
252+
} else if (extras.containsKey(URI_EXTRA)) {
253+
mInputTypeView.setSelection(URI_INDEX);
254+
mUriInput.setText(extras.getString(URI_EXTRA));
255+
}
256+
257+
// It's also possible we're here from LaunchActivity, which did all this work for us.
258+
if (extras.containsKey(APP_DETAILS_EXTRA)) {
259+
mMediaAppDetails = extras.getParcelable(APP_DETAILS_EXTRA);
260+
}
183261
}
184262
}
185263

@@ -211,6 +289,31 @@ private void setupMediaController() {
211289
mBrowser.connect();
212290
}
213291

292+
private MediaAppDetails buildMediaDetailsFromPackage(final String packageName) {
293+
final PackageManager packageManager = getPackageManager();
294+
295+
final Intent mediaBrowserIntent = new Intent(MediaBrowserServiceCompat.SERVICE_INTERFACE);
296+
final List<ResolveInfo> services =
297+
packageManager.queryIntentServices(mediaBrowserIntent,
298+
PackageManager.GET_RESOLVED_FILTER);
299+
for (ResolveInfo info : services) {
300+
if (info.serviceInfo.packageName.equals(packageName)) {
301+
final Drawable icon = info.loadIcon(packageManager);
302+
final String name = info.loadLabel(packageManager).toString();
303+
final String serviceName = info.serviceInfo.name;
304+
final ComponentName serviceComponentName =
305+
new ComponentName(packageName, serviceName);
306+
return new MediaAppDetails(
307+
name,
308+
serviceComponentName,
309+
BitmapUtils.convertDrawable(getResources(), icon));
310+
}
311+
}
312+
313+
// Failed to find package.
314+
return null;
315+
}
316+
214317
private void setupButtons() {
215318

216319
final PreparePlayHandler preparePlayHandler = new PreparePlayHandler(this);

mediacontroller/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<string name="app_icon_desc">App icon for %1$s.string>
2020
<string name="no_apps_found">No Media Apps Foundstring>
2121
<string name="no_apps_details">Could not locate any apps implementing a MediaBrowser.string>
22+
<string name="no_app_for_package">Could not find a media browser for package "%1$s".string>
2223

2324
<string name="monkey_buttons_txt">PUSH BUTTONS!string>
2425
<string name="default_pkg">com.example.android.uampstring>

0 commit comments

Comments
 (0)