I need to download a pdf file and save in device. I have used WebClient process to download a file and show progress while downloading it.
CancellationTokenSource Token= new CancellationTokenSource(); //Initialize a token while start download
webClient.DownloadFileTaskAsync(new Uri(downloadurl), saveLocation); // Download file
Download is working properly. To cancel the download which is in progress, I have used cancellationtokensource as mentioned in below link.
https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads
Token.Cancel(); //Cancellation download
try
{
// check whether download cancelled or not
Token.ThrowIfCancellationRequested();
if(Token.IsCancellationRequested)
{
//Changed button visibility
}
}
catch (OperationCanceledException ex)
{
}
It takes more seconds to cancel the download. Can you please suggest me to reduce the delay in cancelling download?
We have to register token into webclient cancel async process before downloadasync process. We have to maintain order like below,
//Initialize for download process
WebClient webClient = new WebClient();
CancellationTokenSource token = new CancellationTokenSource();
//register token into webclient
token.Register(webClient.CancelAsync);
try
{
webClient.DownloadFileTaskAsync(new Uri(downloadurl), saveLocation); // Download a file
}
catch(Exception ex)
{
//Change button visibility
}
Token.Cancel(); //Cancellation download put in cancel click button event
It doesn't takes even milliseconds and cancellation works fine in both Xamarin.Android and Xamarin.iOS device.
Related
In my IoT mobile app, I created a page showed on iOS device as UIModalPresentationStyle.PageSheet.
During the page load I don't want the page will react to user interaction, in particular I don't want the page will be closed, because the app interacts with a physical device.
The page will be enabled to be closed once all the background tasks will be completed.
I tried to set the page property IsEnabled to false, but again I'm able to close the page.
That's a code snippet from the page constructor
public ParametersListPage(ControlUnitParametersCategory parametersCategory, bool isParametersListReadOnly = false)
{
InitializeComponent();
IsEnabled = false;
On<iOS>().SetModalPresentationStyle(UIModalPresentationStyle.PageSheet);
MessagingCenter.Subscribe<ListParamsViewModel>(this, Constants.ACTION, async (sender) =>
{
IsEnabled = true;
await DisplayAlert(Resource.DoAct, Resource.DoActMsg, "OK");
}
);
What Am I missing?
Thank you
Do you want to disable user actions during interaction? If so, you can try setting the UserInteractionEnabled property to false to disable the user's actions so that the user will never be able to trigger any events (including touchscreens).
For Xamarin.Forms you can refer to the following code:
MyPageRenderer:
[assembly:ExproRenderer(typeof(ParametersListPage),typeof(ParametersListPageRenderer))]
namespace FormsDemo.iOS
{
public class ParametersListPageRenderer:PageRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
this.View.UserInteractionEnabled=false;
}
}
}
If you just want the user not to close the page during interaction, it is better to set a popup reminder.
I'm trying to integrate callkit with pushkit in one of my app in xamarin using Twilio voip. I was able to do so by defining required classes and delegates.
I can receive a call when my app is in foreground. but when my app is backgrounded or killed, its not received.
I have this method in my appdelegate:
[Export("pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:")]
[Preserve(Conditional = true)]
public void DidReceiveIncomingPush(PKPushRegistry registry, PKPushPayload payload, string type, Action completion)
{
try
{
Console.WriteLine("My push is coming (Inside Action method!");
var callerid = payload.DictionaryPayload["twi_from"].ToString();
Console.WriteLine($"from: {callerid}");
completion= delegate {
if (payload != null)
{
TwilioService.Setnotification(payload);
}
};
completion.Invoke();
// Tried using only this
// completion(); but it didn't work.
}catch(Exception ex)
{
Console.WriteLine(ex.message);
}
}
So question is how to bring Native dialer when call is arriving and app is in background or killed. I don't understand how to use "Action" parameter of above method.
I see this error in my device logs:
Info (114) / callservicesd: Application <private> will not be launched because it failed to report an incoming call too many times (or repeatedly crashed.)
Thanks.
Hello i have a blazor page in which i want to display a variable.
This variable gets updated from another thread (Task- which receives data over a websocket) and i want to display it in a thread-safe manner:
Blazor Page
#page "/new"
#inherits NewBase
<button onclick="#(async()=>await OnRunPressed())" class="control-button">Run</button>
NewValue :#socketString
public class NewBase:BlazorComponent
{
[Inject] protected BenchService service { get; set; }
protected CancellationTokenSource src = new CancellationTokenSource();
protected string socketString;
protected async Task OnRunPressed()
{
Task updateTask= Task.Run(async () =>
{
var buffer =new byte[1024];
ClientWebSocket socket = new ClientWebSocket();
await socket.ConnectAsync(new Uri("ws://localhost:8500/monitor"), CancellationToken.None);
while (true)
{
await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
this.socketString = Encoding.UTF8.GetString(buffer);
this.StateHasChanged();
}
},src.Token);
await this.service.HitServerAsync(); //does some stuff while the above task works
src.Cancel();
}
}
Update
Thanks to #Dani now i finally at least get an error :
blazor.server.js:16 POST http://localhost:8500/_blazor/negotiate 500 (Internal Server Error)
Error: Failed to start the connection: Error: Internal Server Error
You may be lacking StateHasChanged(); at the end of the OnRunPressed method
I guess this is a server-side Blazor, right ?
If not, then you should know that Mono on WASM is currently single-threaded...
They are no problem about to call StateHasChanged(); after receive data via websocket. All should to run. I have tested it (as server side) and it runs without issues:
https://github.com/ctrl-alt-d/blazorTestingWebSocketsServerSide/tree/master
Also, I have tested it as client side wasm, and they are several issues:
You are using ArrayPool that is a non netstandard2.0 class.
WebSocket is not able to connect from wasm.
Im trying open pdf`s from a selectable list with a wevbview but when I click in app nothing happens, I have given the app internet permision also read and write(tough not needed) to ext storage. Can anyone give me a hint?
I have tested the google docs version it works with it but there are login and print buttons there where they dont work in webview, and Id like users to save the pdf they pick to view
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.endsWith(".pdf")){
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(url), "application/pdf");
try{
view.getContext().startActivity(intent);
} catch (ActivityNotFoundException e) {
//user does not have a pdf viewer installed
}
} else {
webview.loadUrl(url);
}
return true;
Ok so I changed the code so instead of viewing in the webview it should just download the file. I still have no idea why the above code was not calling the default pdf viewer on the device.I had installed over 5 pdf viewers on my device and made at least 3 of them default to test - didnt work. So in the end I just changed the shouldOverrideUrlLoading to download the file in the ext storage and from then, the user can open it by any app he wants/has installed. Solution:
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (url.endsWith(".pdf")) {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
return false;
}
also added permissions to manifest to access the default download manager and external storage
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>
this fixed it for me.
After I use CloudBlob.BeginUploadFromStream() method to upload a file, I later get a StorageClientException with StorageErrorCode.ResourceNotFound when trying to retrieve the file for a download. If I upload the same file using CloudBlob.UploadFromStream() method, then the blob DOES exist and i can download it.
here's my download code:
var client = _storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference(BLOB_CONTAINER_DOCUMENTS_ADDRESS);
container.CreateIfNotExist();
string blobName = id.ToString();
var newBlob = container.GetBlobReference(blobName);
if (newBlob.Exists())
{
var stream = newBlob.OpenRead();
return stream;
}
else
{
throw new Exception("Blob does not exist!");
}
Exists is an extension method. I'm getting the StorageClientException with the error code ResourceNotFound when I use the BeginUploadFromStream() method
public static bool Exists(this CloudBlob blob)
{
try
{
blob.FetchAttributes();
return true;
}
catch (StorageClientException e)
{
if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
{
return false;
}
else
{
throw;
}
}
}
And my call to upload
var blob = container.GetBlobReference(blobName);
This will NOT throw an exception when i later check if the blob exists
blob.UploadFromStream(fileStream);
This will
AsyncCallback uploadCompleted = new AsyncCallback(OnUploadCompleted);
blob.BeginUploadFromStream(fileStream, uploadCompleted, documentId);
EDIT
As suggested, i didn't have a call to EndUploadFromStream() method. Here is my updated call to upload:
blob.BeginUploadFromStream(fileStream, uploadCompleted, blob);
And my handler
private void OnUploadCompleted(IAsyncResult result)
{
var blob = (CloudBlob) result.AsyncState;
blob.EndUploadFromStream(result);
}
Running this, the EndUploadFromStream() method throws a WebException with the msg: "The request was aborted: The request was canceled." The InnerException is "Cannot close stream until all bytes are written."
Anyone have any idea what's going on here?
BeginUploadFromStream uploads the blob asynchronously, so your method proceeds while the blob uploads on a thread in the background. If the blob hasn't finished uploading -- or if Azure hasn't been told that the upload has completed -- you won't see the blob in storage. Only blobs uploaded through successfully completed transactions are visible.
Could you post the code for OnUploadCompleted?
It looks at first glance as if either the blob is still uploading -- or you've forgotten to call EndUploadFromStream() in your OnUploadCompleted method.
What it sounds like is happening is IIS is cancelling the thread that is being initiated to make the BeginUploadFromStream. Since the storage API is really just manipulating a bunch of REST calls under the hood you can think of these storage calls as web service calls and not like traditional IO.
Check out this topic on HttpKeepAlives, this might solve your problem but as the article pointed out it may impact performance of your site. So you may want to add logic to only enable the keep alive for the requests that are performing the upload.
http://www.jaxidian.org/update/2007/05/05/8/