I followed https://github.com/vimeo/vimeo-networking-java to configure Vimeo client(initialized by that accesstoken) on Android using hardcoded access token (has access to public and private videos). but the call of VimeoClient.getInstance().fetchContent() fails.
public void vimeoSettings(){
String urlPublic = "https://player.vimeo.com/video/496738949";
String urlPrivate = "https://player.vimeo.com/video/496739025";
Configuration.Builder confBuilder = new Configuration.Builder("ACCESS_TOKEN");
//later will generate in runtime and whats the validity?
Configuration configuration = confBuilder.build();
VimeoClient.initialize(configuration);
VimeoClient.getInstance().fetchContent(String.valueOf(Uri.parse(urlPublic)), CacheControl.FORCE_NETWORK, new ModelCallback<Video>(Video.class){
#Override
public void success(Video video) {
if(video != null){
Log.d("webviewactivity","inside vimeo settings - video not null ");
Play play = video.getPlay();
if (play != null) {
VideoFile dashFile = play.getDashVideoFile();
String dashLink = dashFile.getLink();
// load link
VideoFile hlsFile = play.getHlsVideoFile();
String hlsLink = hlsFile.getLink();
// load link
ArrayList<VideoFile> progressiveFiles = play.getProgressiveVideoFiles();
String linkToMp4File = progressiveFiles.get(0).getLink();
webView.load(linkToMp4File);
}
}
}
#Override
public void failure(VimeoError error) {
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
facing these Errors :
E/cr_VariationsUtils: Failed reading seed file "/data/user/0/com.emergingit.emergingstudy/app_webview/variations_seed": /data/user/0/com.emergingit.emergingstudy/app_webview/variations_seed (No such file or directory)
E/chromium: [ERROR:gl_surface_egl.cc(335)] eglChooseConfig failed with error EGL_SUCCESS
what are these errors indicate and, even if I solve this,
is this the right approach to load in Webview as I must have to make my video private with domain restriction for the website use case?
can I use this approach to play in https://github.com/ct7ct7ct7/Android-VimeoPlayer?
I am getting verified first by our token from the backend and then given the URL. after that using the access token and configuring the Vimeo client I need to load the video.
Vimeo official documentation for this kind of private video scenario for android seems really unclear to me and also contacted for help but did not get any response though I have a paid account.
Please help or suggest..!!
Related
I am trying to run the TextToSpeech code from Google Cloud TextToSpeech Service.
Curently stuck at Authentication part referring link Authenticating as a service account
Below is the Code :
public class TexttoSpeech {
/** Demonstrates using the Text-to-Speech API. */
public static void getAudio() throws Exception {
// Instantiates a client
// Below Line is Point of Error in Code
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create()) {
// Set the text input to be synthesized
SynthesisInput input = SynthesisInput.newBuilder().setText("Hello, World!").build();
// Build the voice request, select the language code ("en-US") and the ssml voice
//gender
// ("neutral")
VoiceSelectionParams voice =
VoiceSelectionParams.newBuilder()
.setLanguageCode("en-US")
.setSsmlGender(SsmlVoiceGender.NEUTRAL)
.build();
// Select the type of audio file you want returned
AudioConfig audioConfig =
AudioConfig.newBuilder().setAudioEncoding(AudioEncoding.MP3).build();
// Perform the text-to-speech request on the text input with the selected voice parameters and
// audio file type
SynthesizeSpeechResponse response =
textToSpeechClient.synthesizeSpeech(input, voice, audioConfig);
// Get the audio contents from the response
ByteString audioContents = response.getAudioContent();
byte[] audioArray=audioContents.toByteArray();
String converted= Base64.encodeBase64String(audioArray);
playAudio(converted);
// Write the response to the output file.
try (OutputStream out = new FileOutputStream("output.mp3")) {
out.write(audioContents.toByteArray());
System.out.println("Audio content written to file \"output.mp3\"");
}
}
}
public static void playAudio(String base64EncodedString){
try
{
String url = "data:audio/mp3;base64,"+base64EncodedString;
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(url);
mediaPlayer.prepare();
mediaPlayer.start();
}
catch(Exception ex){
System.out.print(ex.getMessage());
}
}
}
But getting below error on :
java.io.IOException: The Application Default Credentials are not available. They are available
if running in Google Compute Engine. Otherwise, the environment variable
GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials.
See https://developers.google.com/accounts/docs/application-default-credentials for more
information.
Also tried Explicit credentials :
#Throws(IOException::class)
fun authExplicit() {
val projectID = "texttospeech-12345" // dummy id
// val imageUri: Uri =
Uri.fromFile(File("file:\\android_asset\\service_account_file.json"))
// val path=File(imageUri.path).absolutePath
// You can specify a credential file by providing a path to GoogleCredentials.
// Otherwise credentials are read from the GOOGLE_APPLICATION_CREDENTIALS environment
variable.
val credentials =
GoogleCredentials.fromStream(mContext.resources.openRawResource(R.raw.service_account_file))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"))
val storage: Storage =
StorageOptions.newBuilder().setProjectId(projectID).setCredentials(credentials)
.build().service
println("Buckets:")
// Error at storage.lists()
val buckets: Page<Bucket> = storage.list()
for (bucket in buckets.iterateAll()) {
println(bucket.toString())
}
}
But on device it gives error like :
Error getting access token for service account:
Unable to resolve host "oauth2.googleapis.com": No address associated with hostname, iss:
xyz#texttospeech-12345.iam.serviceaccount.com
And on Emulator the error is :
xxxxxxxxx does not have storage.buckets.list access to the Google Cloud project.
Please let me know if you guys need something more.
Any suggestion will be appreciated
Thanks in Advance
Also if I run below command in Cloud SDK :
gcloud auth application-default login
I get this but I didnt understood what its trying to say
You can pass the credentials while creating the client connection.
TextToSpeechSettings settings = TextToSpeechSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(authExplicit("JSON FILE PATH")))
.build();
try (TextToSpeechClient textToSpeechClient = TextToSpeechClient.create(settings)) {
// ... rest of your code
}
// ... rest of your code
And
public static GoogleCredentials authExplicit(String jsonPath) throws IOException {
GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(jsonPath))
.createScoped(Lists.newArrayList("https://www.googleapis.com/auth/cloud-platform"));
return credentials;
}
GoogleCredentials imported from Google Auth Library For Java OAuth2 HTTP
N.B You need to make sure you are able to fetch the JSON file in your application.
I have tried playing vimeo video using webview. But it doesn't look good, it makes the screen scrollable.
Vimeo has suggested one more way to play using native playback, but it has specific requirements to use
The basic requirements for native playback are:
User must be logged in.
User must be the owner of the video.
User must be PRO or higher (or the app must have the "can access owner's video files" capability).
Token must have the video_files scope.
User must be the owner of the API app making the request
I don't have PRO account. How can i use native playback just to test, if all goes well then i will go for vimeo PRO
THIS IS CODE WHICH I AM USING FOR PLAYING USING WEBVIEW
VimeoClient.getInstance().fetchNetworkContent(uri, new ModelCallback<Video>(Video.class) {
#Override
public void success(Video video) {
String html = video.embed != null ? video.embed.html : null;
if(html != null) {
WebView webView = (WebView) findViewById(R.id.webView);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadData(html, "text/html", "utf-8");
}
}
#Override
public void failure(VimeoError error) {
Log.d(TAG, "failure: ");
}
});
}
Is there any other way to play the video?
In my case I used Exoplayer. Exoplayer is more customizable. All you need is to extract the url link from the config link. You may use retrofit to extract the video url.
BASE_URL = "https://player.vimeo.com/video/"
You will need to use a get method like below:
#GET("{id}/{config}")
Call<JsonObject>getVideoLink(#Path("id") String id, #Path("config") String config);
You will get the id from video link. Example: "https://vimeo.com/123456789/" Here the id is: 123456789 .
JsonObject jsonObject = response.body();
JsonObject req = jsonObject.getAsJsonObject("request");
JsonObject file = req.getAsJsonObject("files");
JsonArray arr = file.getAsJsonArray("progressive");
String url = arr.get(0).getAsJsonObject().get("url").getAsString();
Now you can play using this url . Don't forget to initiate Exoplayer first.
Looking at this issue xamarin/Essentials#1322, how do I download a file on both Android ( versions 6-10, Api 23-29 ) and iOS ( version 13.1+ ) that is publicly available (share-able to other apps, such as Microsoft Word). I don't need to give write access to the other apps, just read-only is ok if it must be restricted.
I get the following exception:
[Bug] Android.OS.FileUriExposedException: file:///data/user/0/{AppBundleName}/cache/file.doc exposed beyond app through Intent.getData()
With the following code.
public static string GetCacheDataPath( string fileName ) => Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName);
public static FileInfo SaveFile( string filename, Uri link )
{
using var client = new WebClient();
string path = GetCacheDataPath(filename);
DebugTools.PrintMessage(path);
client.DownloadFile(link, path);
return new FileInfo(path);
}
public async Task Test(Uri link)
{
LocalFile path = await SaveFile("file.doc", link).ConfigureAwait(true);
var url = new Uri($"ms-word://{path.FullName}", UriKind.Absolute);
await Xamarin.Essentials.Launcher.OpenAsync(url).ConfigureAwait(true);
}
With this answer, I created a FileService interface and it works with local private files but I am unable to share the files. Starting with Android Q (10 / Api 29), the following is deprecated.
string path = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath; // deprecated
I get the following exception:
System.UnauthorizedAccessException: Access to the path '/storage/emulated/0/Download/file.doc' is denied. ---> System.IO.IOException: Permission denied
I haven't found any way yet to get a public path for Android 10 with Xamarin.Forms. I've looked at the Android Docs for Content providers but it's in Java, and I can't get it working in C# yet.
Any help would be greatly appreciated.
I did find a Solution
Found a fix
For Android
public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
if ( link is null )
throw new ArgumentNullException(nameof(link));
using System.Net.WebClient client = new System.Net.WebClient();
// MainActivity is the class that loads the application.
// MainActivity.Instance is a property that you set "Instance = this;" inside of OnCreate.
Java.IO.File root = MainActivity.Instance.GetExternalFilesDir(MediaStore.Downloads.ContentType);
string path = Path.Combine(root.AbsolutePath, fileName);
client.DownloadFile(link, path);
return Task.FromResult(new System.IO.FileInfo(path));
}
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
internal static MainActivity Instance { get; private set; }
protected override void OnCreate(Bundle savedInstanceState)
{
...
Instance = this;
...
}
...
}
For iOS
public Task<System.IO.FileInfo> DownloadFile( Uri link, string fileName )
{
if ( link is null )
throw new ArgumentNullException(nameof(link));
using System.Net.WebClient client = new System.Net.WebClient();
string path = Path.Combine(Xamarin.Essentials.FileSystem.CacheDirectory, fileName)
client.DownloadFile(link, path);
return Task.FromResult(new System.IO.FileInfo(path));
}
public async Task Share()
{
// back in shared project, choose a file name and pass the link.
System.IO.FileInfo info = await DependencyService.Get<IDownload>().DownloadFile(new Uri("<enter site>", "file.doc").ConfigureAwait(true);
ShareFile shareFile = new ShareFile(info.FullName, "doc"); // enter the file type / extension.
var request = new ShareFileRequest("Choose the App to open the file", shareFile);
await Xamarin.Essentials.Share.RequestAsync(request).ConfigureAwait(true);
}
Note that for iOS, due to Apple's infinite wisdom... I cannot share the file directly with another app as I can on Android. Sandboxing is good for security but in this case, how they implemented it, it limits options. Both Applications must be pre-registered / pre-allocated in an "App Group" to share files directly. See this Article and the Apple Docs for more information.
I am using Cloudiary service in order to decrease the size of an uploaded video. I am getting back a URL of a picture (which I assume is the first frame of the video) back as a response. When trying to load the video from firebase I am for some reason getting a URL and not a URI. here is my method -
private void loadVideoUri(String storageUri) {
if (StringUtils.isBlank(storageUri)) {
return;
}
// load firebase storage
Task<Uri> downloadUrlTask = FirebaseStorage.getInstance().getReferenceFromUrl(storageUri).getDownloadUrl(); // -> crash happends here
if (getContext() instanceof Activity) {
downloadUrlTask.addOnCompleteListener((Activity) getContext(), mOnDownloadUrlCompleted);
} else {
downloadUrlTask.addOnCompleteListener(mOnDownloadUrlCompleted);
}
}
here is the full error -
java.lang.IllegalArgumentException: Firebase Storage URLs must point to an object in your Storage Bucket. Please obtain a URL using the Firebase Console or getDownloadUrl().
at com.google.firebase.storage.internal.Util.normalize(com.google.firebase:firebase-storage##16.0.5:134)
at com.google.firebase.storage.FirebaseStorage.getReferenceFromUrl(com.google.firebase:firebase-storage##16.0.5:281)
at com.onemdtalent.app.ui.views.mdview.FirebasePlayerView.loadVideoUri(FirebasePlayerView.java:156)
I don't know if you already tested the Google IO application, but there is a cool feature displaying all the tweets including Google IO hashtags.
I really would like to offer the same feature to my users.
I can do something similar using the API, but I would have to create a custom listview, parsing XML/JSON feeds and that's quite overcomplicated! and of course this list will not update automatically and be a livefeed.
In the application, I have just seen that when I turn off wifi, This is indeed a webview with this url:
http://www.google.com/search?%20tbs=mbl%3A1&hl=en&source=hp&biw=1170&bih=668&q=%23io2011&btnG=Search
Here is a screenshot of the app and the same url in the browser
High resolution picture: http://cl.ly/3q1r0c2J3H163E3G2p2X
But using this url in a webview display only a google search, and does not offer same feature.
I know this app will certainly be opensources, but i am so negative about "within next days" that google promise.
We are still waiting for the Twitter app source code!
If you wait 'til after the conference is over, you'll find the source code for the app here. You'll also find last year's application's source code there.
Update:
Just viewed the source code, and you're almost right. It's a webview with this URL: http://www.google.com/search?tbs=mbl%3A1&hl=en&source=hp&biw=1170&bih=668&q=%23io2011&btnG=Search so it just seems you put %20 in there by accident maybe.
Code:
public static final String EXTRA_QUERY = "com.google.android.iosched.extra.QUERY";
public static final String CONFERENCE_HASHTAG = "#io2011";
private String mSearchString;
//onCreate()
final Intent intent = BaseActivity.fragmentArgumentsToIntent(getArguments());
mSearchString = intent.getStringExtra(EXTRA_QUERY);
if (TextUtils.isEmpty(mSearchString)) {
mSearchString = CONFERENCE_HASHTAG;
}
if (!mSearchString.startsWith("#")) {
mSearchString = "#" + mSearchString;
}
//onCreateView
mWebView = (WebView) root.findViewById(R.id.webview);
mWebView.post(new Runnable() {
public void run() {
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(false);
try {
mWebView.loadUrl(
"http://www.google.com/search?tbs="
+ "mbl%3A1&hl=en&source=hp&biw=1170&bih=668&q="
+ URLEncoder.encode(mSearchString, "UTF-8")
+ "&btnG=Search");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Could not construct the realtime search URL", e);
}
}
});
Probably implemented with Loaders API with throttling.
Impatiently waiting for source code as well.