Checking out the MediaController documentation, I noticed that there is a function called sendCommand(...), which requires three parameters:
command: String;
args: Bundle;
cb: ResultReceiver.
But examples of how to use that method are nowhere to be found.
What are the available MediaController#sendCommand(...) default commands and acceptable argument keys and values types?
For example, checking PlaybackState documentation, we can find a constant called ACTION_PLAY_FROM_MEDIA_ID which description is as follows:
Indicates this session supports the play from media id command
This leads us to think that MediaController#sendCommand(...) is able to change a MediaSession's current media by sending it the media ID. How can we do it?
It's known that Google Play Music App's MediaController shares its Media Queue through MediaController#getQueue function.
You can find Commands constants in MediaControllerCompat.
They actually are:
public static final String COMMAND_GET_EXTRA_BINDER =
"android.support.v4.media.session.command.GET_EXTRA_BINDER";
public static final String COMMAND_ADD_QUEUE_ITEM =
"android.support.v4.media.session.command.ADD_QUEUE_ITEM";
public static final String COMMAND_ADD_QUEUE_ITEM_AT =
"android.support.v4.media.session.command.ADD_QUEUE_ITEM_AT";
public static final String COMMAND_REMOVE_QUEUE_ITEM =
"android.support.v4.media.session.command.REMOVE_QUEUE_ITEM";
public static final String COMMAND_REMOVE_QUEUE_ITEM_AT =
"android.support.v4.media.session.command.REMOVE_QUEUE_ITEM_AT";
public static final String COMMAND_ARGUMENT_MEDIA_DESCRIPTION =
"android.support.v4.media.session.command.ARGUMENT_MEDIA_DESCRIPTION";
public static final String COMMAND_ARGUMENT_INDEX =
"android.support.v4.media.session.command.ARGUMENT_INDEX";
For some basic usage samples u can check out its methods, like:
#Override
public void removeQueueItem(MediaDescriptionCompat description) {
long flags = getFlags();
if ((flags & MediaSessionCompat.FLAG_HANDLES_QUEUE_COMMANDS) == 0) {
throw new UnsupportedOperationException(
"This session doesn't support queue management operations");
}
Bundle params = new Bundle();
params.putParcelable(COMMAND_ARGUMENT_MEDIA_DESCRIPTION, description);
sendCommand(COMMAND_REMOVE_QUEUE_ITEM, params, null);
}
Related
I am building an app based on the mobile hub sample app. The sample-app has the API keys stored in a class file AWSconfiguration:
public class AWSConfiguration {
// AWS MobileHub user agent string
public static final String AWS_MOBILEHUB_USER_AGENT =
"MobileHub ********* aws-my-sample-app-android-v0.16";
// AMAZON COGNITO
public static final Regions AMAZON_COGNITO_REGION =
Regions.fromName("us-east-1");
public static String AMAZON_COGNITO_IDENTITY_POOL_ID = "us-east-************6";
// Google Client ID for Web application
public static String GOOGLE_CLIENT_ID ="";//"*********************.apps.googleusercontent.com";
public static final Regions AMAZON_DYNAMODB_REGION =
Regions.fromName("us-east-1");
public static String AMAZON_COGNITO_USER_POOL_ID = "************";
public static String AMAZON_COGNITO_USER_POOL_CLIENT_ID = "*************";
public static String AMAZON_COGNITO_USER_POOL_CLIENT_SECRET = "*************";
private static final AWSMobileHelperConfiguration helperConfiguration = new AWSMobileHelperConfiguration.Builder()
.withCognitoRegion(AMAZON_COGNITO_REGION)
.withCognitoIdentityPoolId(AMAZON_COGNITO_IDENTITY_POOL_ID)
.withCognitoUserPool(AMAZON_COGNITO_USER_POOL_ID,
AMAZON_COGNITO_USER_POOL_CLIENT_ID, AMAZON_COGNITO_USER_POOL_CLIENT_SECRET)
.build();
/**
* #return the configuration for AWSKit.
*/
public static AWSMobileHelperConfiguration getAWSMobileHelperConfiguration() {
return helperConfiguration;
}
}
It seems unsafe to store the client secret key this way. What are the risks?
I experiemnted with hiding the keys in JNI files but could not find the proper entry point in the activity to set the keys before they are called from the mobile helper.
Storing in clear text is generally a bad idea, as you guessed. You could use the android keystore, store it encrypted (the stronger the key, the better), obfuscate it with some unique identifier of your device, or access it via some API you control and secure. It's possible to use some other solution, or a combination of the above possibilities. The final decision comes down to you and what your app needs/abilities are, but there's a few ways to hide it.
SharedPreferences.Editor can be a solution.
Password or something like this are stored in SharedPreferences.
A lot of my users are facing a NullPointerException issue while instantiating content descriptor.
Fatal Exception: java.lang.NullPointerException: Attempt to read from field 'java.lang.String android.content.UriMatcher.mText' on a null object reference
at android.content.UriMatcher.addURI(UriMatcher.java:186)
at com.getsuperapp.chat.db.ContentDescriptor.getUriMatcher(SourceFile:25)
at com.getsuperapp.chat.db.DatabaseProvider.query(SourceFile:33)
at android.content.ContentProvider.query(ContentProvider.java:1017)
at android.content.ContentProvider$Transport.query(ContentProvider.java:238)
at android.content.ContentResolver.query(ContentResolver.java:497)
at android.content.ContentResolver.query(ContentResolver.java:439)
The set of devices and environment can be found here.
The ContentDescriptor file is
/**
* A few constants from other classes used in the file
*
* from UserTable.java
* public static final String PATH = "user_table";
* public static final int PATH_TOKEN = 10;
*/
public class ContentDescriptor {
private static UriMatcher URI_MATCHER = null;
private static Uri BASE_URI = null;
public static UriMatcher getUriMatcher(Context appContext) {
String AUTHORITY = appContext.getPackageName() + ".quickblox";
if (URI_MATCHER == null) {
URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
//The line below is throwing the exception.
URI_MATCHER.addURI(AUTHORITY, UserTable.PATH, UserTable.PATH_TOKEN);
URI_MATCHER.addURI(AUTHORITY, DialogTable.PATH, DialogTable.PATH_TOKEN);
URI_MATCHER.addURI(AUTHORITY, MessageTable.PATH, MessageTable.PATH_TOKEN);
URI_MATCHER.addURI(AUTHORITY, ChatInfoTable.PATH, ChatInfoTable.PATH_TOKEN);
}
return URI_MATCHER;
}
public static Uri getBaseUri(Context appContext) {
String AUTHORITY = appContext.getPackageName() + ".quickblox";
if (BASE_URI == null) {
BASE_URI = Uri.parse("content://" + AUTHORITY);
}
return BASE_URI;
}
}
Let me know if you need any further information. Can anyone provide me some visibility into this. I'm unable to reproduce the crash at my end.
EDIT
Guys stop brushing this into any other NPE category without reading. Its running on a lot of devices without trouble. The initialisation parameters are constants. The line on which its crashing is commented in the code too.
What are the values of your AUTHORITY, PATHs and PATH_TOKENs (all of them)? Depending on the values and the Android version the app is running on your app might fall into the bug fixed in UriMatcher. I guess this is the place you want to start digging into. Also, did you receive the bug report from the developer console or some king of bug reporting library? If yes, what Android version have the reports in common? It might help to reproduce the failure. Or get a ton of devices/emulators running on different versions and try to get it manually.
I am using YouTubeAndroidPlayerApi - 1.2.1, to show Youtube videos in my application. I get the url's from backend and they come in different formats. For example,
public static final String DOMAIN_1 = "https://www.youtube.com/watch?v=";
public static final String DOMAIN_2 = "http://www.youtube.com/watch?v=";
public static final String DOMAIN_3 = "https://youtu.be/";
public static final String DOMAIN_4 = "http://www.youtube.com/embed/";
public static final String DOMAIN_5 = "https://www.youtube.com/embed/";
All the above urls have VideoID at the end, and I am able to get VideoID and use,
Intent intent = YouTubeStandalonePlayer.createVideoIntent((Activity) activity,
Const.YouTube.API_KEY, videoId, 0,
true, true);
to play them. But my problem is, there are also urls such as,
https://www.youtube.com/watch?t=15&v=video_id
https://www.youtube.com/watch?v=video_id&list=PL1RpYLGwB6WM409EJBVM1MS9bs3httFse&index=1
and since there are other characters in it, I couldn't extract the videoID.
Is there a way I can use URL with createVideoIntent() or is there any other way i can use URLs to work with YouTubeAndroidPlayerApi.
[EDIT]
If i can't use URL, can someone help me with getting a regex, for extracting videoID from the above Urls?
Use regular expression to cut off the rest of the url
I need to be when you press the buttons in the usual android I could switch to music in my standard audio player for android while the music is playing. How can you interact with a standard audio player for android?
Music player is not standard thing on Android and vendors can come with different app than others (i.e. Sony is good exapmple). Controlling media app can be doable but final effect depends on what app is really installed (and used, as user can have more than one). You may be able to control some, but other may remain immune to your attempts. You can try this code - will work for Google Music for example):
public static final String SERVICECMD = "com.android.music.musicservicecommand";
public static final String CMDNAME = "command";
public static final String CMDSTOP = "stop";
AudioManager mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(mAudioManager.isMusicActive()) {
Intent i = new Intent(SERVICECMD);
i.putExtra(CMDNAME , CMDSTOP );
YourApplicationClass.this.sendBroadcast(i);
}
other commands are
public static final String CMDTOGGLEPAUSE = "togglepause";
public static final String CMDPAUSE = "pause";
public static final String CMDPREVIOUS = "previous";
public static final String CMDNEXT = "next";
Commands are taken from android/music/MediaPlaybackService.java
I want to cater for LICENSE_OLD_KEY in my android license policy.
I was going to modify the ServerManagedPolicy as it doesn't cater for this, as far as I can tell, it just seems to look for Policy.LICENSED or Policy.NOT_LICENSED in processServerResponse method:
public void processServerResponse(int response, ResponseData rawData) {
// Update retry counter
if (response != Policy.RETRY) {
setRetryCount(0);
} else {
setRetryCount(mRetryCount + 1);
}
if (response == Policy.LICENSED) {
// Update server policy data
Map<String, String> extras = decodeExtras(rawData.extra);
mLastResponse = response;
setValidityTimestamp(extras.get("VT"));
setRetryUntil(extras.get("GT"));
setMaxRetries(extras.get("GR"));
} else if (response == Policy.NOT_LICENSED) {
// Clear out stale policy data
setValidityTimestamp(DEFAULT_VALIDITY_TIMESTAMP);
setRetryUntil(DEFAULT_RETRY_UNTIL);
setMaxRetries(DEFAULT_MAX_RETRIES);
}
setLastResponse(response);
mPreferences.commit();
}
I'd like to know what the response code is for LICENSE_OLD_KEY because that doesn't exist in Policy:
public static final int LICENSED = 0x0100;
public static final int NOT_LICENSED = 0x0231;
public static final int RETRY = 0x0123;
I had a look here, but I can't find anywhere that lists the name and values.
I can see that there are a list of server response codes in LicenseValidator but they don't match up to those in Policy:
// Server response codes.
private static final int LICENSED = 0x0;
private static final int NOT_LICENSED = 0x1;
private static final int LICENSED_OLD_KEY = 0x2;
private static final int ERROR_NOT_MARKET_MANAGED = 0x3;
private static final int ERROR_SERVER_FAILURE = 0x4;
private static final int ERROR_OVER_QUOTA = 0x5;
private static final int ERROR_CONTACTING_SERVER = 0x101;
private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
private static final int ERROR_NON_MATCHING_UID = 0x103;
Giving it some thought I decided to try displaying the reason codes returned by the Google Play server on my phone, using AlertDialog's. Here is what I found:
Selecting LICENSED, in the Developer console profile, returned the number 256, as per Policy.LICENSED.
Selecting NOT_LICENSED returned the number 561, again as per Policy.NOT_LICENSED.
Finally selecting LICENSED_OLD_KEY returned the number 256, which is the same as Policy.LICENSED.
So it would seem that LICENSED_OLD_KEY is no longer used, or rather there is no distinction between LICENSED and LICENSED_OLD_KEY. Which is a bit confusing given the information that google provide in their documentation here.
Just to note, I did try uninstalling my app and selecting the different options in the developer console a few times, but it always resulted in the same answer!
The code you're looking at is only a reference implementation. It can't know how you would want to deal with a LICENSED_OLD_KEY situation in detail. The documentation suggests you might want to limit access to the current app, or to your server data from the current app, and ask the user to update and use the latest version. There's nothing much a reference implementation can provide to enable you to deal with all these situations. You can and should modify the code to treat LICENSED_OLD_KEY separately.
There's no indication for LICENSED_OLD_KEY "not being used anymore" because it's still handled as a server response in LicenseValidator.java and "OLD_KEY" refers to an older version of your app, not an older version of Google Play server handling.