DRM WideVine video not playing from android cast sender application - android

I am using the following cast receiver
When I connect my android sender to chromecast device, it show a black screen and never plays video.
https://github.com/googlecast/CastReferencePlayer
I'm setting licenseUrl for widevine in receiver as follow:
sampleplayer.CastPlayer.prototype.preloadVideo_ = function(mediaInformation) {
this.log_('preloadVideo_');
var self = this;
var url = mediaInformation.contentId;
var protocolFunc = sampleplayer.getProtocolFunction_(mediaInformation);
if (!protocolFunc) {
this.log_('No protocol found for preload');
return false;
}
var host = new cast.player.api.Host({
'url': url,
'mediaElement': self.mediaElement_
});
host.onError = function() {
self.preloadPlayer_.unload();
self.preloadPlayer_ = null;
self.showPreviewModeMetadata(false);
self.displayPreviewMode_ = false;
self.log_('Error during preload');
};
host.licenseUrl = event.data.customData.licenseUrl;
self.preloadPlayer_ = new cast.player.api.Player(host);
self.preloadPlayer_.preload(protocolFunc(host));
return true;
};
host.licenseUrl = event.data.customData.licenseUrl;
I've hosted it on a https server which is registered on developers console.
I'm passing custom data as licenseUrl in a json object.
The code of my android sender setting media info is below.
private MediaInfo buildMediaInfo() {
MediaMetadata movieMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE);
movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, "Subtitle");
movieMetadata.putString(MediaMetadata.KEY_TITLE, "Title");
jsonObj = new JSONObject();
try{
jsonObj.put("licenseUrl","https://wv.test.expressplay.com/hms/wv/rights/?ExpressPlayToken=token-value");
}catch (JSONException e){
Log.e(null,"Failed to add description to the json object", e);
}
/*drmModel.getData().getStreamURL()*/
return new MediaInfo.Builder("https://pathOfMystream.mpd")
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType("application/dash+xml")
.setMetadata(movieMetadata)
.setCustomData(jsonObj)
.setStreamDuration(player.getDuration()*1000)
.build();
}
What changes are further required ?
Do I need to edit receiver? If yes, then what edits are needed?
Is the string name in customData "licenseUrl" needs to be
changed?
CORS is enabled on the S3 server which is hosting the video contents.
Please help! I'm stuck here for more than a week.
Thank you.

I figured out that event.data.customData was undefined while connecting from android sender application.
So I used event.data.media.customData
And accessed the key as follow:
if(event.data.media.customData['licenseUrl'] !== null){
console.log('setting license URL from mobile');
host.licenseUrl = event.data.media.customData.licenseUrl;
}

Related

How to open a url in Blackberry Access from an Android app

I have successfully opened the blackberry access from our IOS app using the url scheme access://open? , but it seems to be not working on Android. Our application is not integrated with blackberry sdk .
For anyone who needs it you can open the blackberry access from your app using the blackberry access appid com.good.gdgma.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(urlString));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setPackage("com.good.gdgma");
try {
getApplicationContext().startActivity(intent);
}
catch(ActivityNotFoundException ex) {
showNotInstalledDialog(App.BLACKBERRY_ACCESS);
}
There is a setting the in application configuration policy for BlackBerry Access that enables or disables this feature. It's called "Allow external apps to open HTTP/HTTPS URLs through BlackBerry Access" and is set for the app config for BlackBerry Access within BlackBerry UEM. This setting applies to all non BlackBerry Dynamics methods of opening BlackBerry Access.
If you were to integrate with the BlackBerry Dynamics SDK the recommended method is to use the BlackBerry Dynamics Shared Services framework to call the Open HTTP URL Service. It's available for both iOS and Android. Here's some Android sample code to use it.
Here's a code snippet that does just that:
private static final String SERVICE_ID = "com.good.gdservice.open-url.http";
private static final String SERVICE_VERSION = "1.0.0.0";
private static final String ACCESS_ENTITLEMENT_ID = "com.good.gdgma";
private static final String HTTP_OPEN_URL_SERVICE_METHOD_NAME = "open";
....
//Get the service providers for the Open HTTP URL service.
List<GDServiceProvider> providers = GDAndroid.getInstance().getServiceProvidersFor(SERVICE_ID, SERVICE_VERSION,
GDServiceType.GD_SERVICE_TYPE_APPLICATION);
//Ensure an provider of the Open HTTP URL service was found.
if(providers == null || providers.size() == 0)
{
//No providers found.
showError("No Open HTTP URL were found.");
}
else
{
boolean foundAccess = false;
String yourURL = "www.whereEverYouWantToGo.com";
for (int count = 0; count < providers.size(); count++)
{
GDServiceProvider provider = providers.get(count);
//Ensure BlackBerry Access was found.
if (provider.getIdentifier().equalsIgnoreCase(ACCESS_ENTITLEMENT_ID))
{
foundAccess = true;
String address = providers.get(count).getAddress();
Map<String, Object> params = new HashMap<>();
params.put("url", yourURL);
try
{
//Launch BlackBerry Access.
GDServiceClient.sendTo(address, SERVICE_ID, SERVICE_VERSION,
HTTP_OPEN_URL_SERVICE_METHOD_NAME, params, null,
GDICCForegroundOptions.PreferPeerInForeground);
} catch (GDServiceException e)
{
showError(e.toString());
}
}
}
if (!foundAccess)
{
showError("BlackBerry Access not found.");
}
}

How can I get image url of all the uploaded images from the cloudinary server?

I have successfully uploaded 6 image one by one on Cloudinary. Now I want to get all images URL. How can I get in android mobile client side?
I am using code below.
List<String> imageList = new ArrayList<>();
Map config = ObjectUtils.asMap(
"cloud_name", "shank",
"api_key", "644617911542992",
"api_secret", "oW3bQk8luOT9UlEkRsH21KoQkxY");
Cloudinary cloudinary = new Cloudinary(config);
Api api = cloudinary.api();
JSONObject outerObject = null;
String jsonNext = null;
boolean ifWeHaveMoreResources = true;
while (ifWeHaveMoreResources) {
try {
outerObject = new JSONObject(api.resources(ObjectUtils.asMap("max_results", 10, "next_cursor", jsonNext)));
if (outerObject.has("next_cursor")) {
jsonNext = outerObject.get("next_cursor").toString();
ifWeHaveMoreResources = true;
} else {
ifWeHaveMoreResources = false;
}
JSONArray jsonArray = outerObject.getJSONArray("resources");
for (int i = 0, size = jsonArray.length(); i < size; i++) {
JSONObject objectInArray = jsonArray.getJSONObject(i);
String public_id = objectInArray.get("public_id").toString();
String url = objectInArray.get("secure_url").toString();
imageList.add(url);
}
} catch (Exception e) {
e.printStackTrace();
}
}
But it gives the exception.
java.lang.Exception: Administration API is not supported for mobile applications
Please help me to resolve this issue.
java.lang.Exception: Administration API is not supported for mobile applications
Due to security reasons, Admin API is not available with client SDK like Android.
You should use some kind of proxy server to make this call to Cloudinary (you can use Cloud Functions for Firebase for example)

Set User Agent for RemoteMediaClient and MediaMetaData of Google Cast(TM)

I integrated support for Google Cast (TM) to my app. My app has own user agent. I block other user agents on the server side. I found that when media is played on Android TV via Google Cast (TM) client uses user agent as a browser. Is it possible to set user agent for RemoteMediaClient and MediaMetaData?
private void loadRemoteMedia(boolean autoPlay) {
if (mCastSession == null) {
return;
}
RemoteMediaClient remoteMediaClient = mCastSession.getRemoteMediaClient();
if (remoteMediaClient == null) {
return;
}
remoteMediaClient.load(buildMediaInfo(), autoPlay);
}
private MediaInfo buildMediaInfo() {
MediaMetadata mediaMetadata = new MediaMetadata(MediaMetadata.MEDIA_TYPE_TV_SHOW);
mediaMetadata.putString(MediaMetadata.KEY_TITLE, "title");
return new MediaInfo.Builder(selectedStreamingURL)
.setContentType("application/x-mpegurl")
.setStreamType(MediaInfo.STREAM_TYPE_LIVE)
.setMetadata(mediaMetadata)
.build();
}
For all Cast devices, the Chrome browser is the user agent and controls the HTTP request headers. For DRM content and if you use the CAF receiver, there are various options for you to control access to your content:
https://developers.google.com/cast/docs/caf_receiver_features#drm

YouTube video upload showing "Required parameter: part" error for some users

I'm trying to find out why some of our users are getting the error "Required parameter: part" when trying to upload a video into YouTube using YouTube API v3. Below you can see the code that we use for uploading videos. The method params are valid strings that aren't short or too long.
int shareYoutube(#NonNull Uri mediaUri, String mime, String mediaTitle, String postMessage, String accountName)
{
int error = ERR_NO_ERROR;
try {
// Developer tags not supported yet
//https://code.google.com/p/gdata-issues/issues/detail?id=5012
// Authorize the request.
GoogleAccountCredential credential = GoogleAccountCredential.usingOAuth2(getApplicationContext(), Arrays.asList(YouTubeScopes.YOUTUBE_UPLOAD));
credential.setSelectedAccountName(accountName);
// This object is used to make YouTube Data API requests.
YouTube.Builder builder = new YouTube.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential);
builder.setApplicationName("TEST APP");
YouTube youtube = builder.build();
// Add extra information to the video before uploading.
Video video = new Video();
// set privacy
VideoStatus status = new VideoStatus();
status.setPrivacyStatus("public");
video.setStatus(status);
// Most of the video's metadata is set on the VideoSnippet object.
VideoSnippet snippet = new VideoSnippet();
snippet.setTitle(mediaTitle);
snippet.setDescription(postMessage);
// Film & Animation https://gist.github.com/dgp/1b24bf2961521bd75d6c
snippet.setCategoryId("1");
// Set the keyword tags that you want to associate with the video.
List<String> tags = new ArrayList<>();
tags.add("animation");
tags.add("cartoon");
tags.add("2d animation");
tags.add("drawing");
snippet.setTags(tags);
// Add the completed snippet object to the video resource.
video.setSnippet(snippet);
String fileFormat = "video/*";
InputStreamContent mediaContent = new InputStreamContent(fileFormat, getContentResolver().openInputStream(mediaUri));
// Insert the video. The command sends three arguments. The first
// specifies which information the API request is setting and which
// information the API response should return. The second argument
// is the video resource that contains metadata about the new video.
// The third argument is the actual video content.
YouTube.Videos.Insert videoInsert = youtube.videos().insert("snippet,statistics,status", video, mediaContent);
// Insert to a channel
//videoInsert.setOnBehalfOfContentOwnerChannel();
// Set the upload type and add an event listener.
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();
// Indicate whether direct media upload is enabled. A value of
// "True" indicates that direct media upload is enabled and that
// the entire media content will be uploaded in a single request.
// A value of "False," which is the default, indicates that the
// request will use the resumable media upload protocol, which
// supports the ability to resume an upload operation after a
// network interruption or other transmission failure, saving
// time and bandwidth in the event of network failures.
uploader.setDirectUploadEnabled(false);
YouTubeCallbackListener callback = new YouTubeCallbackListener();
uploader.setProgressListener(callback);
// Call the API and upload the video.
Video returnedVideo = videoInsert.execute();
synchronized (callback) {
if (!callback.hasCallbackResult()) {
try {
callback.wait();
error = callback.error;
} catch (InterruptedException e) {
e.printStackTrace();
error = ERR_POST_CANCELED;
}
} else {
error = callback.error;
}
}
if (ERR_NO_ERROR == error && null != returnedVideo)
{
Intent notificationIntent = new Intent(
Intent.ACTION_VIEW,
Uri.parse("http://www.youtube.com/watch?v="+returnedVideo.getId()));
mPendingIntent = PendingIntent.getActivity(getBaseContext(), 0, notificationIntent, 0);
}
}
catch (UserRecoverableAuthIOException userRecoverableException)
{
error = ERR_UNABLE_TO_AUTH_ACCOUNT;
try {
GoogleAuthUtil.getTokenWithNotification(
getApplicationContext(), accountName, "oauth2:" + YouTubeScopes.YOUTUBE_UPLOAD, null);
} catch (IOException e) {
} catch (GoogleAuthException e) {
}
} catch (GoogleJsonResponseException e) {
error = ERR_POST_ERROR;
Crashlytics.logException(e);
} catch (IOException e) {
error = ERR_POST_ERROR;
Crashlytics.logException(e);
} catch (Throwable t) {
error = ERR_POST_ERROR;
Crashlytics.logException(t);
}
return error;
}
Error:
400 Bad Request { "errors" : [ { "domain" : "global", "reason" : "required", "message" : "Required parameter: part", "locationType" : "parameter", "location" : "part" } ], "code" : 400, "message" : "Required parameter: part" }
Any thoughts on what could be happening here?
The problem was our proguard script. All we had to do was include the following line to it.
-keep class com.google.api.** { *; }

How to change PJSIP sip port for android version?

I am trying to use the different SIP port other than 5060.
I change the port of following code, but only the source port is changed.
The destination port of SIP server is still 5060.
// Create SIP transport. Error handling sample is shown
TransportConfig sipTpConfig = new TransportConfig();
sipTpConfig.setPort(Long.parseLong(port, 10));
/* Create transports. */
try {
ep.transportCreate(pjsip_transport_type_e.PJSIP_TRANSPORT_UDP, sipTpConfig);
}catch(Exception e){
System.out.println(e);
}
Does anyone have the idea how to do?
Thanks in advance!
You have to modify the account configuration:
final String acc_id = String.format(Locale.ENGLISH, "sip:%s#%s", username, domain);
final String registrar = String.format(Locale.ENGLISH, "sip:%s", domain);
final String proxy = String.format(Locale.ENGLISH, "sip:%s:%d;transport=%s;port=%d", domainip, port, protocol, port);
accCfg.setIdUri(acc_id);
accCfg.getRegConfig().setRegistrarUri(registrar);
AuthCredInfoVector creds = accCfg.getSipConfig().getAuthCreds();
creds.clear();
if (username.length() != 0) {
creds.add(new AuthCredInfo("Digest", "*", username, 0, password));
}
StringVector proxies = accCfg.getSipConfig().getProxies();
proxies.clear();
if (proxy.length() != 0) {
proxies.add(proxy);
}
accCfg.getNatConfig().setIceEnabled(true); // Enable ICE
lastRegStatus = null;
account.modify(accCfg);

Categories

Resources