I'm trying to download a file to iOS using the CrossDownloadManager, but I can not find the file anywhere! I debugged and I see that it recognizes the HTTP and "donwload" the file but can not find the file.
I'm using Ipad ios11.
I do not know if there is an easier way, but this plugin seemed more viable.
My code:
CrossDownloadManager.Current.CollectionChanged += (sender, e) =>
System.Diagnostics.Debug.WriteLine(
"[DownloadManager] " + e.Action +
" -> New items: " + (e.NewItems?.Count ?? 0) +
" at " + e.NewStartingIndex +
" || Old items: " + (e.OldItems?.Count ?? 0) +
" at " + e.OldStartingIndex
);
var Url2 = "https://mysite/myfile.pdf"; //here i put my file, its ok.
DownloadFile(Url2);
}
public async void DownloadFile(String fileName)
{
await Task.Yield();
//await Navigation.PushPopupAsync(new DownloadingPage());
await Task.Run(() =>
{
var downloadManager = CrossDownloadManager.Current;
var file = downloadManager.CreateDownloadFile(fileName);
downloadManager.Start(file, true);
while (isDownloading)
{
isDownloading = IsDownloading(file);
}
});
//await Navigation.PopAllPopupAsync();
if (!isDownloading)
{
await DisplayAlert("File Status", "File Donwload","OK");
//DependencyService.Get<IToast>().ShowToast(“Baixou”);
}
}
public bool IsDownloading(IDownloadFile file)
{
if (file == null) return false;
switch (file.Status)
{
case DownloadFileStatus.INITIALIZED:
case DownloadFileStatus.PAUSED:
case DownloadFileStatus.PENDING:
case DownloadFileStatus.RUNNING:
return true;
case DownloadFileStatus.COMPLETED:
case DownloadFileStatus.CANCELED:
case DownloadFileStatus.FAILED:
return false;
default:
throw new ArgumentOutOfRangeException();
}
}
public void AbortDownloading()
{
CrossDownloadManager.Current.Abort(File);
}
And in iOS part, I put:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
Downloaded();
return base.FinishedLaunching(app, options);
}
public void Downloaded()
{
CrossDownloadManager.Current.PathNameForDownloadedFile = new System.Func<IDownloadFile, string>
(file => {
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
System.Diagnostics.Debug.WriteLine(Environment.SpecialFolder.Resources);
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Resources), fileName);
});
}
public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler)
{
CrossDownloadManager.BackgroundSessionCompletionHandler = completionHandler;
}
Related
We are working on a Xamarin Forms app that is supposed to upload photos to API in the background. The app is being custom-made for a client by their request, so they will set their phones to whatever permissions need to be set.
Below works fine if the charging cable is plugged in.
I am using BGTaskScheduler (iOS13+) and queuing both types of tasks (BGProcessingTaskRequest and BGAppRefreshTaskRequest) so that if the cable plugged in it would fire off BGProcessingTaskRequest and if not it would wait for BGAppRefreshTaskRequest to get its processing time.
I have added RefreshTaskId and UploadTaskId to Info.plist
AppDelegate.cs in iOS project looks following
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
BGTaskScheduler.Shared.Register(UploadTaskId, null, task => HandleUpload(task as BGProcessingTask));
BGTaskScheduler.Shared.Register(RefreshTaskId, null, task => HandleAppRefresh(task as BGAppRefreshTask));
return base.FinishedLaunching(app, options);
}
public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler)
{
Console.WriteLine("HandleEventsForBackgroundUrl");
BackgroundSessionCompletionHandler = completionHandler;
}
public override void OnActivated(UIApplication application)
{
Console.WriteLine("OnActivated");
}
public override void OnResignActivation(UIApplication application)
{
Console.WriteLine("OnResignActivation");
}
private void HandleAppRefresh(BGAppRefreshTask task)
{
HandleUpload(task);
}
public override void DidEnterBackground(UIApplication application)
{
ScheduleUpload();
}
private void HandleUpload(BGTask task)
{
var uploadService = new UploadService();
uploadService.EnqueueUpload();
task.SetTaskCompleted(true);
}
private void ScheduleUpload()
{
var upload = new BGProcessingTaskRequest(UploadTaskId)
{
RequiresNetworkConnectivity = true,
RequiresExternalPower = false
};
BGTaskScheduler.Shared.Submit(upload, out NSError error);
var refresh = new BGAppRefreshTaskRequest(RefreshTaskId);
BGTaskScheduler.Shared.Submit(refresh, out NSError refreshError);
if (error != null)
Console.WriteLine($"Could not schedule BGProcessingTask: {error}");
if (refreshError != null)
Console.WriteLine($"Could not schedule BGAppRefreshTask: {refreshError}");
}
The mechanism that does the upload UploadService is using NSUrlSession, it also writes a temporary file to use CreateUploadTask(request, NSUrl.FromFilename(tempFileName)) that is supposed to work in the background, whole mechanism looks following:
public NSUrlSession uploadSession;
public async void EnqueueUpload()
{
var accountsTask = await App.PCA.GetAccountsAsync();
var authResult = await App.PCA.AcquireTokenSilent(App.Scopes, accountsTask.First())
.ExecuteAsync();
if (uploadSession == null)
uploadSession = InitBackgroundSession(authResult.AccessToken);
var datastore = DependencyService.Get<IDataStore<Upload>>();
var uploads = await datastore.GetUnuploaded();
foreach (var unUploaded in uploads)
{
try
{
string folder = unUploaded.Description;
string subfolder = unUploaded.Category;
if (string.IsNullOrEmpty(folder) || string.IsNullOrEmpty(subfolder))
continue;
var uploadDto = new Dtos.Upload
{
FolderName = folder,
SubFolderName = subfolder,
Image = GetImageAsBase64(unUploaded.ImagePath)
};
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var fileName = Path.GetFileName(unUploaded.ImagePath);
var tempFileName = Path.Combine(documents, $"{fileName}.txt");
string stringContent = await new StringContent(JsonConvert.SerializeObject(uploadDto), Encoding.UTF8, "application/json").ReadAsStringAsync();
await File.WriteAllTextAsync(tempFileName, stringContent);
using (var url = NSUrl.FromString(UploadUrlString))
using (var request = new NSMutableUrlRequest(url)
{
HttpMethod = "POST",
})
{
request.Headers.SetValueForKey(NSObject.FromObject("application/json"), new NSString("Content-type"));
try
{
uploadSession.CreateUploadTask(request, NSUrl.FromFilename(tempFileName));
}
catch (Exception e)
{
Console.WriteLine($"NSMutableUrlRequest failed {e.Message}");
}
}
}
catch (Exception e)
{
if (e.Message.Contains("Could not find a part of the path"))
{
await datastore.DeleteItemAsync(unUploaded.Id);
Console.WriteLine($"deleted");
}
Console.WriteLine($"uploadStore failed {e.Message}");
}
}
}
private string GetImageAsBase64(string path)
{
using (var reader = new StreamReader(path))
using (MemoryStream ms = new MemoryStream())
{
reader.BaseStream.CopyTo(ms);
return Convert.ToBase64String(ms.ToArray());
}
}
public NSUrlSession InitBackgroundSession(string authToken = null, IDataStore<Upload> dataStore = null)
{
Console.WriteLine("InitBackgroundSession");
using (var configuration = NSUrlSessionConfiguration.CreateBackgroundSessionConfiguration(Identifier))
{
configuration.AllowsCellularAccess = true;
configuration.Discretionary = false;
configuration.AllowsConstrainedNetworkAccess = true;
configuration.AllowsExpensiveNetworkAccess = true;
if (string.IsNullOrWhiteSpace(authToken) == false)
{
configuration.HttpAdditionalHeaders = NSDictionary.FromObjectsAndKeys(new string[] { $"Bearer {authToken}" }, new string[] { "Authorization" });
}
return NSUrlSession.FromConfiguration(configuration, new UploadDelegate(dataStore), null);
}
}
}
public class UploadDelegate : NSUrlSessionTaskDelegate, INSUrlSessionDelegate
{
public IDataStore<Upload> Datastore { get; }
public UploadDelegate(IDataStore<Upload> datastore)
{
this.Datastore = datastore;
}
public override void DidCompleteWithError(NSUrlSession session, NSUrlSessionTask task, NSError error)
{
Console.WriteLine(string.Format("DidCompleteWithError TaskId: {0}{1}", task.TaskIdentifier, (error == null ? "" : " Error: " + error.Description)));
if (error == null)
{
ProcessCompletedTask(task);
}
}
public void ProcessCompletedTask(NSUrlSessionTask sessionTask)
{
try
{
Console.WriteLine(string.Format("Task ID: {0}, State: {1}, Response: {2}", sessionTask.TaskIdentifier, sessionTask.State, sessionTask.Response));
if (sessionTask.Response == null || sessionTask.Response.ToString() == "")
{
Console.WriteLine("ProcessCompletedTask no response...");
}
else
{
var resp = (NSHttpUrlResponse)sessionTask.Response;
Console.WriteLine("ProcessCompletedTask got response...");
if (sessionTask.State == NSUrlSessionTaskState.Completed && resp.StatusCode == 201)
{
Console.WriteLine("201");
}
}
}
catch (Exception ex)
{
Console.WriteLine("ProcessCompletedTask Ex: {0}", ex.Message);
}
}
public override void DidBecomeInvalid(NSUrlSession session, NSError error)
{
Console.WriteLine("DidBecomeInvalid" + (error == null ? "undefined" : error.Description));
}
public override void DidFinishEventsForBackgroundSession(NSUrlSession session)
{
Console.WriteLine("DidFinishEventsForBackgroundSession");
}
public override void DidSendBodyData(NSUrlSession session, NSUrlSessionTask task, long bytesSent, long totalBytesSent, long totalBytesExpectedToSend)
{
}
}
Everything works if the iOS charger cable is plugged in, however, if it isn't nothing fires. I have a network debugging set up with plenty of logging into the console, and I can see that nothing happens on iPhone.
"Low power mode" setting on iOS is off.
I have watched Background execution demystified and I am setting session configuration.Discretionary = false;
How do I make the NSUrlSession upload task to fire when iOS charger cable is unplugged on iOS 14.4?
Following works without charging cable:
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public Action BackgroundSessionCompletionHandler { get; set; }
public static string UploadTaskId { get; } = "XXX.upload";
public static NSString UploadSuccessNotificationName { get; } = new NSString($"{UploadTaskId}.success");
public static string RefreshTaskId { get; } = "XXX.refresh";
public static NSString RefreshSuccessNotificationName { get; } = new NSString($"{RefreshTaskId}.success");
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
BGTaskScheduler.Shared.Register(UploadTaskId, null, task => HandleUpload(task as BGProcessingTask));
BGTaskScheduler.Shared.Register(RefreshTaskId, null, task => HandleAppRefresh(task as BGAppRefreshTask));
return base.FinishedLaunching(app, options);
}
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
return true;
}
public override void HandleEventsForBackgroundUrl(UIApplication application, string sessionIdentifier, Action completionHandler)
{
Console.WriteLine("HandleEventsForBackgroundUrl");
BackgroundSessionCompletionHandler = completionHandler;
}
public override void OnActivated(UIApplication application)
{
Console.WriteLine("OnActivated");
var uploadService = new UploadService();
uploadService.EnqueueUpload();
}
public override void OnResignActivation(UIApplication application)
{
Console.WriteLine("OnResignActivation");
}
private void HandleAppRefresh(BGAppRefreshTask task)
{
task.ExpirationHandler = () =>
{
Console.WriteLine("BGAppRefreshTask ExpirationHandler");
var refresh = new BGAppRefreshTaskRequest(RefreshTaskId);
BGTaskScheduler.Shared.Submit(refresh, out NSError refreshError);
if (refreshError != null)
Console.WriteLine($"BGAppRefreshTask ExpirationHandler Could not schedule BGAppRefreshTask: {refreshError}");
};
HandleUpload(task);
}
public override void DidEnterBackground(UIApplication application) => ScheduleUpload();
private void HandleUpload(BGTask task)
{
Console.WriteLine("HandleUpload");
var uploadService = new UploadService();
uploadService.EnqueueUpload();
task.SetTaskCompleted(true);
}
private void ScheduleUpload()
{
Console.WriteLine("ScheduleUpload");
var upload = new BGProcessingTaskRequest(UploadTaskId)
{
RequiresNetworkConnectivity = true,
RequiresExternalPower = false
};
BGTaskScheduler.Shared.Submit(upload, out NSError error);
var refresh = new BGAppRefreshTaskRequest(RefreshTaskId);
BGTaskScheduler.Shared.Submit(refresh, out NSError refreshError);
if (error != null)
Console.WriteLine($"Could not schedule BGProcessingTask: {error}");
if (refreshError != null)
Console.WriteLine($"Could not schedule BGAppRefreshTask: {refreshError}");
}
}
then Upload service:
public class UploadService : IUploadService
{
private const string uploadUrlString = "https://Yadyyadyyada";
public async void EnqueueUpload()
{
var accountsTask = await App.PCA.GetAccountsAsync();
var authResult = await App.PCA.AcquireTokenSilent(App.Scopes, accountsTask.First())
.ExecuteAsync();
try
{
var uploadDto = new object();
var message = new HttpRequestMessage(HttpMethod.Post, uploadUrlString);
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken);
message.Content = new StringContent(JsonConvert.SerializeObject(uploadDto), Encoding.UTF8, "application/json");
var response = await httpClient.SendAsync(message);
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
}
}
catch (Exception e)
{
Console.WriteLine($"EnqueueUpload {e.Message}");
}
}
}
I just started learning Vaadin 8 and my first example is Upload button. I was stuck with an issue where I could not solve the problem for many hours and hours.
Here it is,
I am returning PipedOutputStream in the receiveUpload method,
Here is the code for receiveUpload method,
public OutputStream receiveUpload(String filename, String mimeType) {
this.fileName = filename;
this.mimeType = mimeType;
try {
pipedOutputStream = new PipedOutputStream();
pipedInputStream = new PipedInputStream(pipedOutputStream);
if (filename == null || filename.trim().length() == 0) {
upload.interruptUpload();
} else {
}
} catch (Exception e) {
e.printStackTrace();
}
return pipedOutputStream;
}
In the uploadSucceeded method, I need to take the pipedinputstream and send it another method to load the stream into the database
public void uploadSucceeded(SucceededEvent event) {
try {
fileUploadOperation.upload(pipedInputStream); --> I need to push all the stream data in one go into a method to generate a file at the business layer
} catch (Exception e) {
e.printStackTrace();
}
}
When I was running the application, it hangs out for a long time and I could not figure out where it is. Later I could notice that both piped input and piped output streams should be created in separate threads or at least one of them in a separate thread but don't know how to handle it.
Any help
I am pasting the complete class for more information,
public class WebCommunityView implements Receiver, FailedListener, SucceededListener, StartedListener, FinishedListener {
private PipedOutputStream pipedOutputStream = null;
private PipedInputStream pipedInputStream = null;
private Upload upload = null;
private String fileName = null, mimeType = null;
private Grid<FileListProperties> fileListGrid = null;
public final static WebCommunityView newInstance(WebContentScreen screen) {
vw.initBody();
return vw;
}
protected void initBody() {
VerticalLayout verticalLayout = new VerticalLayout();
fileListGrid = new Grid<FileListProperties>();
fileListGrid.addColumn(FileListProperties::getCreatedDate).setCaption("Date");
fileListGrid.addColumn(FileListProperties::getFileName).setCaption("File Name");
fileListGrid.addColumn(FileListProperties::getUserName).setCaption("User Name");
fileListGrid.addComponentColumn(this::buildDownloadButton).setCaption("Download");
fileListGrid.setItems(loadGridWithFileInfo());
upload = new Upload("", this);
upload.setImmediateMode(false);
upload.addFailedListener((Upload.FailedListener) this);
upload.addSucceededListener((Upload.SucceededListener) this);
upload.addStartedListener((Upload.StartedListener) this);
upload.addFinishedListener((Upload.FinishedListener) this);
Label fileUploadLabel = new Label("Label"));
verticalLayout.addComponent(currentListLabel);
verticalLayout.addComponent(fileListGrid);
verticalLayout.addComponent(fileUploadLabel);
verticalLayout.addComponent(upload);
mainbody.addComponent(verticalLayout);
}
#Override
public void uploadSucceeded(SucceededEvent event) {
try {
//Model Layer
fileUploadOperation.upload(pipedInputStream);
fileUploadOperation.commit();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void uploadFailed(FailedEvent event) {
if (event.getFilename() == null) {
Notification.show("Upload failed", Notification.Type.HUMANIZED_MESSAGE);
}
try {
//Model Layer
fileUploadOperation.abort();
} catch (Exception e) {
e.printStackTrace();
}
}
public OutputStream receiveUpload(String filename, String mimeType) {
this.fileName = filename;
this.mimeType = mimeType;
try {
pipedOutputStream = new PipedOutputStream();
new Thread() {
public void run() {
try {
System.out.println("pipedInputStream Thread started");
pipedInputStream = new PipedInputStream(pipedOutputStream);
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
if (filename == null || filename.trim().length() == 0) {
screen.displayMessage("Please select a file to upload !", WebContentScreen.MESSAGE_TYPE_WARNING);
upload.interruptUpload();
} else {
Properties properties = new Properties();
properties.setProperty("NAME", fileName);
properties.setProperty("MIME_TYPE", mimeType);
//Model Layer
fileUploadOperation.initialize(properties);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("pipedOutputStream:"+pipedOutputStream);
return pipedOutputStream;
}
private List<FileListProperties> loadGridWithFileInfo() {
List<FileListProperties> list = null;
DateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
try {
list = new ArrayList<FileListProperties>(1);
Collection<FileInfo> fileInfoList = fileCommandQuery.lstFilesForDownload();
for (Iterator iterator = fileInfoList.iterator(); iterator.hasNext();) {
FileInfo fileInfo = (FileInfo) iterator.next();
Properties properties = fileInfo.getProperties();
Collection<String> mandatoryParameters = fileInfo.getMandatoryProperties();
FileListProperties fileListProperties = new FileListProperties();
for (Iterator iterator2 = mandatoryParameters.iterator(); iterator2.hasNext();) {
String key = (String) iterator2.next();
String value = properties.getProperty(key);
if (key != null && key.equalsIgnoreCase("NAME")) {
fileListProperties.setFileName(value);
} else if (key != null && key.equalsIgnoreCase("USER_NAME")) {
fileListProperties.setUserName(value);
} else if (key != null && key.equalsIgnoreCase("CREATED_DATE")) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(1550566760000L);
fileListProperties.setCreatedDate(dateFormat.format(calendar.getTime()));
}
}
if (fileListProperties != null) {
list.add(fileListProperties);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
dateFormat = null;
}
return list;
}
private Button buildDownloadButton(FileListProperties fileListProperties) {
Button button = new Button("...");
button.addClickListener(e -> downloadFile(fileListProperties));
return button;
}
private void downloadFile(FileListProperties fileListProperties) {
}
}
The problem in your example is that you need to do the actual file handling in a separate thread. The Viritin add-on contains a component called UploadFileHandler that simplifies this kind of usage a lot. It will provide you InputStream to consume. The integration test for the component contains this kind of usage example.
Also, my recent blog entry about the subject might help.
I have a HTML5 web app I can view through my mobile devices.
I have an img control that would download an image using an ashx asp.net handler.
I updated via a timer.
I am trying to port this over to a Windows Phone 8.1 app instead.
The image seems to take ages to update (if at all). This is my code:
long tick = DateTime.Now.Ticks;
BitmapImage bmp =new BitmapImage(new Uri("http://my url/Mobile/NewFrame.ashx?b=1a=9A5C3-E1945-3D315-BB43C&c=3&m=1&t=" + tick));
imgFrame1.Source = bmp;
Is this the correct way?
this is the full code:
private async void LogIn()
{
using (var client = new HttpClient())
{
var resp = await client.PostAsJsonAsync("http://my url/UserManagement/Login.aspx/Test",
new { username = "", password = "", hubuserid = hubuserid });
var str = await resp.Content.ReadAsStringAsync();
var jsonObj = JsonConvert.DeserializeObject<UserLogIn>(str);
if (jsonObj.d.Success)
{
UpdateConnectionState("Logged In");
}
else
{
UpdateConnectionState("Not Logged In");
}
}
}
public class D
{
public string __type { get; set; }
public bool Success { get; set; }
}
public class UserLogIn
{
public D d { get; set; }
}
private string hubuserid = "";
public string Uptime { get; set; }
private byte ImageIsLoaded = 1;
private async void UpdateTime(int data)
{
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
try
{
txtInfo.Text = data.ToString();
if (ImageIsLoaded == 1)
{
ImageIsLoaded = 0;
long tick = DateTime.Now.Ticks;
BitmapImage bi = new BitmapImage(new Uri("http://www.informedmotion.co.uk/Mobile/NewFrame.ashx?b=1a=9A5C3-E1945-3D315-BB43C&c=3&m=1&t=" + tick, UriKind.Absolute));
bi.DownloadProgress += bi_DownloadProgress;
bi.ImageOpened += bi_ImageOpened; }
}
catch (Exception ex)
{
txtInfo.Text = ex.ToString();
}
});
}
void bi_DownloadProgress(object sender, DownloadProgressEventArgs e)
{
//throw new NotImplementedException();
}
void bi_ImageOpened(object sender, RoutedEventArgs e)
{
ImageIsLoaded = 1;
imgFrame1.Source = (BitmapImage)sender;
}
private void imgFrame1_ImageOpened(object sender, RoutedEventArgs e)
{
ImageIsLoaded = 1;
}
private void imgFrame1_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
ImageIsLoaded = 1;
}
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
imgFrame1.ImageFailed += imgFrame1_ImageFailed;
imgFrame1.ImageOpened += imgFrame1_ImageOpened;
ConnectToHub();
}
private void ConnectToHub()
{
proxy.On<int>("broadcastMessage", data =>
{
UpdateTime(data);
});
connection.Start().ContinueWith(task =>
{
if (task.IsFaulted)
{
UpdateConnectionState("Not Connected");
ConnectToHub();
}
else
{
UpdateConnectionState(string.Format("Success! Connected with client connection id {0}", connection.ConnectionId));
hubuserid = connection.ConnectionId;
LogIn();
}
});
connection.Error += ex =>
{
UpdateConnectionState(string.Format("An error occurred {0}", ex.Message));
};
connection.Closed += () =>
{
UpdateConnectionState(string.Format("Connection with client id {0} closed", connection.ConnectionId));
ConnectToHub();
};
connection.Reconnected += () =>
{
//LogIn();
UpdateConnectionState("The connection was re-established");
};
}
Windows.UI.Core.CoreDispatcher dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
async void UpdateConnectionState(string state)
{
await dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
try{
txtInfo.Text = state;
}
catch (Exception ex)
{
txtInfo.Text = ex.ToString();
}
});
}
static HubConnection connection = new HubConnection("http://www.informedmotion.co.uk/");
IHubProxy proxy = connection.CreateHubProxy("ChatHub");
If you're going to download the image, then you probably want to hooked the
Image.DownloadProgress event
Image.ImageOpened event
ImageOpened will fire once the download is complete, so at that moment you can set the .Source to it.
While it is downloading (if it's a huge image) you can either show the previous image or a place holder image (with progress bar maybe?)
BitmapImage bi = new BitmapImage(new Uri("http://www.google.com/myimage.bmp", UriKind.Absolute));
bi.DownloadProgress += bi_DownloadProgress;
bi.ImageOpened += bi_ImageOpened;
hiddenImage.Source = bi; // we need to set it to an element in the visual tree so the
// events will fire, we're going to use the hiddenImage
void bi_DownloadProgress(object sender, DownloadProgressEventArgs e)
{
throw new NotImplementedException();
}
void bi_ImageOpened(object sender, RoutedEventArgs e)
{
throw new NotImplementedException();
}
<!-- myImage is your image that you use to show stuff -->
<!-- hiddenImage is the image we use to fire the event -->
<Image x:Name="myImage"></Image>
<Image x:Name="hiddenImage" Visibility="Collapsed"></Image>
here is my post request to server:
public WWW POST(string url, string post)
{
var www = new WWW(url, Encoding.UTF8.GetBytes(post));
StartCoroutine(WaitForRequest(www));
while (!www.isDone && www.error == null)
{
Console.Write("downloading...");
Thread.Sleep(1000);
}
return www;
}
private IEnumerator WaitForRequest(WWW www)
{
while (!www.isDone && www.error == null) { yield return new WaitForSeconds(0.1f);}
// check for errors
if (www.error != null)
{
Debug.Log("WWW Error: " + www.error);
}
}
it works fine in Unity Editor, but it freeze to unlimited loop in Web Player Build version. Does anybody know why?
okay, the problem was in coroutines
public IEnumerator LoginFinished(string message)
{
string url = "URL";
Console.Write("Post on: " + url);
var response = _httpServer.POST(url, message.Substring(message.IndexOf('?') + 1));
while ( !response.isDone && response.error == null )
{
yield return new WaitForEndOfFrame();
}
Console.Write("response: " + Zlib.Unzip(response.bytes));
}
public WWW POST(string url, string post)
{
var www = new WWW(url, Encoding.UTF8.GetBytes(post));
StartCoroutine(WaitForRequest(www));
return www;
}
private IEnumerator WaitForRequest(WWW www)
{
yield return www;
if (www.error != null)
{
Debug.Log("WWW Error: " + www.error);
}
}
if i do
StartCoroutine(LoginFinished("authdata"));
it works just fine.
This is my downloader plugin for my phonegap and jquery app..this plugin is working but i want to change that fixed URL ("http://farm9.staticflickr.com/8010/7293758472_823d2eef5c_z.jpg") to current URL..(i want download jpg from current url).thanx
Downloader.java
package com.phonegap.plugins.downloader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
public class Downloader extends Plugin {
#Override
public PluginResult execute(String action, JSONArray args, String callbackId) {
if (!action.equals("downloadFile"))
return new PluginResult(PluginResult.Status.INVALID_ACTION);
try {
String fileUrl = args.getString(0);
JSONObject params = args.getJSONObject(1);
String fileName = params.has("fileName") ?
params.getString("fileName"):
fileUrl.substring(fileUrl.lastIndexOf("/")+1);
String dirName = params.has("dirName") ?
params.getString("dirName"):
"sdcard/PhotoBunch";
Boolean overwrite = params.has("overwrite") ? params.getBoolean("overwrite") : false;
return this.downloadUrl(fileUrl, dirName, fileName, overwrite, callbackId);
} catch (JSONException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
} catch (InterruptedException e) {
e.printStackTrace();
return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
}
}
private PluginResult downloadUrl(String fileUrl, String dirName, String fileName, Boolean overwrite, String callbackId) throws InterruptedException, JSONException {
try {
Log.d("PhoneGapLog", "Downloading "+fileUrl + " into " + dirName + "/" + fileName);
File dir = new File(dirName);
if (!dir.exists()) {
Log.d("PhoneGapLog", "directory " + dirName + " created");
dir.mkdirs();
}
File file = new File(dirName, fileName);
if (!overwrite && file.exists()) {
Log.d("DownloaderPlugin", "File already exist");
JSONObject obj = new JSONObject();
obj.put("status", 1);
obj.put("total", 0);
obj.put("file", fileName);
obj.put("progress", 100);
return new PluginResult(PluginResult.Status.OK, obj);
}
URL url = new URL(fileUrl);
HttpURLConnection ucon = (HttpURLConnection) url.openConnection();
ucon.setRequestMethod("GET");
ucon.setDoOutput(true);
ucon.connect();
Log.d("PhoneGapLog", "Download start");
InputStream is = ucon.getInputStream();
byte[] buffer = new byte[1024];
int readed = 0,
progress = 0,
totalReaded = 0,
fileSize = ucon.getContentLength();
FileOutputStream fos = new FileOutputStream(file);
while ((readed = is.read(buffer)) > 0) {
fos.write(buffer, 0, readed);
totalReaded += readed;
int newProgress = (int) (totalReaded*100/fileSize);
if (newProgress != progress)
progress = informProgress(fileSize, newProgress, fileName, callbackId);
}
fos.close();
Log.d("PhoneGapLog", "Download finished");
JSONObject obj = new JSONObject();
obj.put("status", 1);
obj.put("total", fileSize);
obj.put("file", fileName);
obj.put("progress", progress);
return new PluginResult(PluginResult.Status.OK, obj);
}
catch (FileNotFoundException e) {
Log.d("PhoneGapLog", "File Not Found: " + e);
return new PluginResult(PluginResult.Status.ERROR, 404);
}
catch (IOException e) {
Log.d("PhoneGapLog", "Error: " + e);
return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
}
}
private int informProgress(int fileSize, int progress, String fileName, String callbackId) throws InterruptedException, JSONException {
JSONObject obj = new JSONObject();
obj.put("status", 0);
obj.put("total", fileSize);
obj.put("file", fileName);
obj.put("progress", progress);
PluginResult res = new PluginResult(PluginResult.Status.OK, obj);
res.setKeepCallback(true);
success(res, callbackId);
//Give a chance for the progress to be sent to javascript
Thread.sleep(100);
return progress;
} }
downloader.js
function Downloader() {}
Downloader.prototype.downloadFile = function(fileUrl, params, win, fail) {
//Make params hash optional.
if (!fail) win = params;
PhoneGap.exec(win, fail, "Downloader", "downloadFile", [fileUrl, params]);
};
PhoneGap.addConstructor(function() {
PhoneGap.addPlugin("downloader", new Downloader());
PluginManager.addService("Downloader", "com.phonegap.plugins.downloader.Downloader");
});
onClick="download()"
function download() {
window.plugins.downloader.downloadFile("http://farm9.staticflickr.com/8010/7293758472_823d2eef5c_z.jpg", {overwrite: true},
function(res) {
alert(JSON.stringify(result));
}, function(error) {
alert(error);
}
); }
currentURL : its the filename / complete path of the file you are downloading from a server
example :
onclick="download(myfile.zip)"
function download(fileName) {
window.plugins.downloader.downloadFile(currentUrl, {overwrite: true},
function(res) {
alert(JSON.stringify(result));},
function(error) {
alert(error);
}
); }
You want to do something like this:
onclick="download(this.src)"
function download(currentUrl) {
window.plugins.downloader.downloadFile(currentUrl, {overwrite: true},
function(res) {
alert(JSON.stringify(result));
}, function(error) {
alert(error);
}
); }