Xamarin forms CrossMediaManager play from resource - xamarin.forms

I am trying to play mp3 from my resource with CrossMediaManager i have tried
await CrossMediaManager.Current.Play("file:///AV.Droid/Resources/raw/gong.mp3");
await CrossMediaManager.Current.Play("file:///AV.Droid/Resources/raw/gong.mp3");
await CrossMediaManager.Current.Play("file:///android_assets/gong.mp3");
await CrossMediaManager.Current.PlayFromResource("gong.mp3"); as Android resource in drawable
based on this Xamarin Forms MediaManager Source property
the methods doest take 3 parameters anymore so i have tried this
await CrossMediaManager.Current.Play("android.resource://[PackageName]/raw/myfile";
and from shared
await CrossMediaManager.Current.Play("gong.mp3"); saved as embeded resouce

Related

How to evaluate the result of Share.RequestAsync in Xamarin forms

Iam using Xamarin Share to share a URI. Is there anyway to evaluate the result if it was shared or cancelled. From the share dialog the user either share or cancel sharing.
public async Task ShareUri(string uri)
{
await Share.RequestAsync(new ShareTextRequest
{
Uri = uri,
Title = "Share Web Link"
});
}
No, there is no way to do this as that function just returns a void.
If you look at native development too, there's no way to get that information on either platform due to privacy reasons (unless the device is jailbroken)

How do I create a Storage Reference for dynamic Images in Firebase Storage

I am currently building a catalog App and these catalogs are basically images that I have saved in firebase storage. I am currently using the code below to make reference to them.
However, these images need to be updated on a weekly basis with new images. This seems to generate a new link for each image when I change the images in the firebase storage. I am maintaining the name and folder location for these particular images despite updating them. How can I implement this in my App without having to change the code "image link" in my App?
Is it possible to make reference the file name that is maintained despite the content being changed? In summary, I would like to make a storage reference that I do not need to change in my app despite me changing the image content in firebase storage? Please share some code snippets if you have such an implementation. Thanks
ViewPager viewPager;
ViewPagerAdapter adapter;
private String[] images = {
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame1.jpg?alt=media&token=b3917686-090f-43fb-852e-0365ac67dd6e",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame2.jpg?alt=media&token=25e4eb76-5361-42a6-9bfd-6e3b1153611f",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame3.jpg?alt=media&token=a5d4c8b9-9ecb-4ea1-a095-557955db1d19",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame4.jpg?alt=media&token=b4598019-13b3-4600-aa49-86fd0a8c5c64",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame5.jpg?alt=media&token=a4991bfe-d3b4-4f1c-be65-55ddfd1de7ba",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame6.jpg?alt=media&token=e8b43bb6-c967-495f-b5e2-336f082225b6",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame7.jpg?alt=media&token=0f135b82-1a05-4585-a511-bbab35a5613a",
"https://firebasestorage.googleapis.com/v0/b/zamcatalog.appspot.com/o/Game%2Fgame8.jpg?alt=media&token=ab8a9fcf-db2d-4c9c-afd8-969a4db22a8c"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
viewPager = (ViewPager)findViewById(R.id.viewpager);
adapter = new ViewPagerAdapter(gameActivity.this,images);
viewPager.setAdapter(adapter);
}
}"
I think you should look into passing the cloud storage location (gs://bucket-name/folders...\imageName.jpg) instead of the download URL. This storage location should not change as long as you don't change your file names or folder location. You can use the Firebase storage API to access your files/images using the cloud storage location:
// Create a reference to a file from a Google Cloud Storage URI
StorageReference gsReference = storage.getReferenceFromUrl("gs://bucket/images/stars.jpg");
I highly recommend you read the Cloud Storage for Firebase documentation:
https://firebase.google.com/docs/storage/android/start
https://firebase.google.com/docs/storage/android/download-files

Xamarin Forms Azure App Service ADAL Logout not working as expected

We are currently writing a Xamarin Forms Azure Mobile application, using client flow, AAD authentication, refresh tokens etc.
Most of this is working as expected. However, logging out of the application does not work properly. It completes the logout process for both Android and iOS - but upon redirection to the login screen, hitting sign in will never prompt the user with the Microsoft login as expected, it will sign them straight back into the app.
To add a little bit of background, this app has been implemented as per Adrian Hall's book,
current link: https://adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/
with the above described options and configurations.
I have also read through the 30 days of Zumo (also by Adrian Hall) blog on this, and every single post I can find on here relating to this.
My current logout code is as follows:
public async Task LogoutAsync()
{
var loginProvider = DependencyService.Get<ILoginProvider>();
client.CurrentUser = loginProvider.RetrieveTokenFromSecureStore();
var authUri = new Uri($"{client.MobileAppUri}/.auth/logout");
using (var httpClient = new HttpClient())
{
if (IsTokenExpired(client.CurrentUser.MobileServiceAuthenticationToken))
{
var refreshed = await client.RefreshUserAsync();
}
httpClient.DefaultRequestHeaders.Add("X-ZUMO-AUTH", client.CurrentUser.MobileServiceAuthenticationToken);
await httpClient.GetAsync(authUri);
}
// Remove the token from the cache
loginProvider.RemoveTokenFromSecureStore();
//Remove the cookies from the device - so that the webview does not hold on to the originals
DependencyService.Get<ICookieService>().ClearCookies();
// Remove the token from the MobileServiceClient
await client.LogoutAsync();
}
As far as I can tell, this includes everything I have found so far - i.e. calling the /.auth/logout endpoint, removing the token locally, clearing the cookies from the device (as we log in inside a webview) and lastly calling the LogoutAsync() method from the MobileServiceClient.
Am I missing anything? Or is there a way we can force log out from this environment? As I know you can't "invalidate" an OAuth token, you have to wait until it expires - but to my mind, the /.auth/logout endpoint is supposed to handle this within the Azure environment? Though I'm just not sure to what extent.
Any help is appreciated.
We are currently writing a Xamarin Forms Azure Mobile application, using client flow, AAD authentication, refresh tokens etc. Most of this is working as expected. However, logging out of the application does not work properly.
I assumed that if you use the server flow for logging with AAD, the logout processing may works as expected. As you described that you used client flow, since you have clear the client cache for token, I assumed that the issue may caused by the LoginAsync related (ADAL part) logic code, you need to check your code, or you could provide the logging related code for us to narrow this issue.

IdentityServer 3 refresh user with refresh token

We are trying to set up Identity Server 3 in the right way.
We got authentication working fine and we manage to retrieve the refresh token.
The client application is using Angular.
Now when the acces_token expires any calls to the rest api fails (we managed to get it to return 401) but we are wondering how to re-authenticate the user.
In our tests, any api call made from Javascript is failing (401) but as soon as the page is refreshed the whole mechanism is kicking in. We do see that we are redirected to the identity server but it does not show up the login page, we are sent back to the client application with new tokens apparently.
What I would like to do is to refresh the access token without having to force the user to refresh the page.
What I'm not sure though is whose responsibility is it? Is that the client application (website) or the angular application? In other word, should the application handle this transparently for Angular or should angular do something when it receives a 401, in which case, I'm not too sure how the information will flow back to the web app.
Any clue?
Additional Information: We are using OpenId Connect
I got it working!
As I said in the comments I used this article. The writer is referencing a very nice lib that I am using as well.
Facts:
Identity Server 3 is requesting the client secret upon access token refresh
One should not store the refresh_token or the client_secret on the javascript application as they are considered unsafe (see the article)
So I chose to send the refresh_token as en encrypted cookie sith this class (found of ST BTW, just can't find the link anymore, sorry...)
public static class StringEncryptor
{
public static string Encrypt(string plaintextValue)
{
var plaintextBytes = plaintextValue.Select(c => (byte) c).ToArray();
var encryptedBytes = MachineKey.Protect(plaintextBytes);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedValue)
{
try
{
var encryptedBytes = Convert.FromBase64String(encryptedValue);
var decryptedBytes = MachineKey.Unprotect(encryptedBytes);
return new string(decryptedBytes.Select(b => (char)b).ToArray());
}
catch
{
return null;
}
}
}
The javascript application is getting the value from the cookie. It then deletes the cookie to avoid that thing to be sent over and over again, it is pointless.
When the access_token becomes invalid, I send an http request to the application server with the encrypted refresh_token. That is an anonymous call.
The server contacts the identity server and gets a new access_token that is sent back to Javascript. The awesome library queued all other requests so when I'm back with my new token, I can tell it to continue with authService.loginConfirmed();.
The refresh is actually pretty easy as all you have to do is to use the TokenClient from IdentityServer3. Full method code:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> RefreshToken(string refreshToken)
{
var tokenClient = new TokenClient(IdentityServerConstants.IdentityServerUrl + "/connect/token", "my-application-id", "my-application-secret");
var response = await tokenClient.RequestRefreshTokenAsync(StringEncryptor.Decrypt(refreshToken));
return Json(new {response.AccessToken});
}
Comments are welcome, this is probably the best way to do that.
For future reference - using refresh tokens in an angular (or other JS) application is not the correct way as a refresh token is too sensitive to store in the browser. You should use silent renew based on the identityserver cookie to get a new access token. Also see the oidc-client-js javascript library, as this can manage silent renew for you.

Upload large file to Cloud Service in Web Api

After read below posts.
How to increase the temp folder size of web role.
Too small temp folder size of web role.
I understood there is a limitation for uploading large file to cloud service. And seems like windows azure doesn't allocate large size of space for web role by default.
So I was trying to find a way to break it. One of the ways I have been testing successfully is grasp the stream of post request and read it through block by block without reading it from the temp folder. Below is what I done. please review it .
CloudBlobClient blobClient = CreateBlobClient(account);
BlobRequestOptions options = CreateBlobRequestOpt();
CloudBlobContainer container = blobClient.GetContainerReference(sContainerName);
bool b = container.CreateIfNotExist();
CloudBlob blob = container.GetBlobReference(sBlobName);
blob.UploadFromStream(postFileStream, options);
I just passed the postFileStream which I got from Request.Files[0].InputStream in the controller of Asp.net MVC to the CloudBlobClient. and the CloudBlobClient which from Azure Storage Library SDK will read the stream block by block. In this way this will support the large file post. In my test. Even the 2GB file can works fine.
But I also want to make it work in the Asp.net Web Api. and I found the Request in Api controller is System.Net.Http.HttpRequestMessage. It is different from the one in MVC controller named with System.Web.HttpRequestBase. So How can I get the post request file stream in Web Api Controller like in the MVC controller? thanks.
You can get file content(s) using Request.Content.ReadAsMultipartAsync() method.
You can try something like this:
IEnumerable<HttpContent> contents = Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider()).Result.Contents;
foreach (var content in contents)
{
//...
//create your blob object...
//...
blob.UploadFromStream(content.ReadAsStreamAsync().Result);
}

Resources