since I updated targetSdkVersion to 29 I am facing many troubles, this one realted to downloading - installing - updating my app. The apk with the new version is downloaded successfully (because I find it through the file explorer in my phone) but I do not think is installed properly. Once the process finishes it looks like the screen is restarted because it blinks, but the app is not updated (and I know it because in the main screen it shows the version). My code is:
public static boolean openFile(String intentAction) { // in this case it is Intent.ACTION_INSTALL_PACKAGE
try {
File file = new File(Environment.getExternalStorageDirectory().toString() + "/" + "myApp.apk");
if (file.exists()) {
Uri uri;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) {
uri = Uri.fromFile(file);
} else {
uri = FileProvider.getUriForFile(appContext, appContext.getPackageName() + ".provider", file);
}
return installPackage(file, uri);
}
} catch (Exception e) {
generateExceptionLog(e);
}
return false;
}
private static boolean installPackage(File file, Uri uri) {
PackageInstaller packageInstaller = appContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL);
params.setAppPackageName(file.getAbsolutePath());
try {
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
OutputStream packageInSession = session.openWrite("package", 0, -1);
InputStream input;
input = appContext.getContentResolver().openInputStream(uri);
if (input != null) {
generateInfoLog("input.available: " + input.available());
byte[] buffer = new byte[16384];
int n;
while ((n = input.read(buffer)) >= 0) {
packageInSession.write(buffer, 0, n);
}
} else {
generateExceptionLog("INSTALLATION FAILED");
}
packageInSession.close();
input.close();
//Intent intent2 = new Intent(appContext, ActMain.class);
Intent intent2 = new Intent(appContext, LauncherReceiver.class);
intent2.setAction(ACTION_PACKAGE_INSTALED);
//intent.setAction(Intent.PACKAGE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
appContext,
sessionId,
intent2,
PendingIntent.FLAG_UPDATE_CURRENT);
IntentSender statusReceiver = pendingIntent.getIntentSender();
session.commit(statusReceiver);
} catch (Exception e) {
generateExceptionLog(e);
return false;
}
return true;
}
My Receiver:
public class LauncherReceiver extends BroadcastReceiver {
public static final String ACTION_PACKAGE_INSTALED = "com.gim.androidv2.action.PACKAGE_INSTALED";
#Override
public void onReceive(Context context, Intent intent) {
Intent startIntent = new Intent(context, ActMain.class);
intent.setAction(ACTION_PACKAGE_INSTALED);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(startIntent);
}
}
And the manifest:
<receiver android:name=".LauncherReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.aaa.aaa.action.START"></action>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Related
I'm creating a mobile application using Xamarin forms, As part of my implementation, I have a requirement to to show file chooser on clicking on camera icon which is loaded in webView and load the image to webView. currently file chooser is being shown, but image is not getting added.
public override bool OnShowFileChooser(Android.Webkit.WebView webView, Android.Webkit.IValueCallback filePathCallback, FileChooserParams fileChooserParams) {
Intent takePictureIntent = new Intent(MediaStore.ActionImageCapture);
if (takePictureIntent.ResolveActivity(mContext.PackageManager) != null) {
Java.IO.File photoFile = null;
try {
string folder = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
photoFile = new Java.IO.File(folder, "image" + DateTime.Now.Millisecond + ".png");
takePictureIntent.PutExtra("PhotoPath", mCameraPhotoPath);
//photoFile = createImageFile();
//takePictureIntent.PutExtra("PhotoPath", mCameraPhotoPath);
} catch (Exception e) {
Console.WriteLine("catch the Exception" + e);
}
if (photoFile != null) {
mCameraPhotoPath = "file:" + photoFile.AbsolutePath;
//pictureUri = FileProvider.GetUriForFile(mContext, "asdasd", photoFile);
takePictureIntent.PutExtra(Android.Provider.MediaStore.ExtraOutput, photoFile);
} else {
takePictureIntent = null;
}
}
Intent contentSelectionIntent = new Intent(Intent.ActionGetContent);
contentSelectionIntent.AddCategory(Intent.CategoryOpenable);
contentSelectionIntent.SetType(file_type);
Intent[] intentArray;
if (takePictureIntent != null) {
intentArray = new Intent[] {
takePictureIntent
};
} else {
intentArray = new Intent[0];
}
Intent chooserIntent = new Intent(Intent.ActionChooser);
chooserIntent.PutExtra(Intent.ExtraIntent, contentSelectionIntent);
chooserIntent.PutExtra(Intent.ExtraTitle, "File chooser");
chooserIntent.PutExtra(Intent.ExtraInitialIntents, intentArray);
//mContext.StartActivity(chooserIntent);
mContext.StartActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE);
return true;
}
private Java.IO.File createImageFile() {
// Create an image file name
string timeStamp = Android.OS.SystemClock.CurrentThreadTimeMillis().ToString();
string imageFileName = "JPEG_" + timeStamp + "_";
Java.IO.File storageDir;
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Gingerbread) {
storageDir = mContext.CacheDir;
} else {
storageDir = mContext.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures);
}
//new Java.IO.File(mContext.GetExternalFilesDir(null).AbsolutePath);
Java.IO.File imageFile = Java.IO.File.CreateTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
return imageFile;
}
At first, please add the following code into the AndroidManifest.xml to declare the permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.Read_EXTERNAL_STORAGE" />
And then request the permission in the MainActivity's construction method.
var read = await Permissions.RequestAsync<Permissions.StorageRead>();
var write = await Permissions.RequestAsync<Permissions.StorageWrite>();
Finally, please override the OnActivityResult method of the Mainactivity:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (data != null)
{
if (requestCode == INPUT_FILE_REQUEST_CODE)// the value of the INPUT_FILE_REQUEST_CODE
{
if (null == this.message)
{
return;
}
this.message.OnReceiveValue(WebChromeClient.FileChooserParams.ParseResult((int)resultCode, data));
this.message = null;
}
}
}
Im trying to download a PDF document from my app and display it in IBooks or at least make it available to read some how when its completed downloading.
I followed the download example from Xamarin which allows me download the PDF and save it locally. Its being save in the wrong encoding also.
This is what I've tried so far.
private void PdfClickHandler()
{
var webClient = new WebClient();
webClient.DownloadStringCompleted += (s, e) => {
var text = e.Result; // get the downloaded text
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localFilename = $"{_blueways}.pdf";
// writes to local storage
File.WriteAllText(Path.Combine(documentsPath, localFilename), text);
InvokeOnMainThread(() => {
new UIAlertView("Done", "File downloaded and saved", null, "OK", null).Show();
});
};
var url = new Uri(_blueway.PDF);
webClient.Encoding = Encoding.UTF8;
webClient.DownloadStringAsync(url);
}
Do not use DownloadStringAsync for "binary" data, use DownloadDataAsync:
Downloads the resource as a Byte array from the URI specified as an asynchronous operation.
private void PdfClickHandler ()
{
var webClient = new WebClient ();
webClient.DownloadDataCompleted += (s, e) => {
var data = e.Result;
string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string localFilename = $"{_blueways}.pdf";
File.WriteAllBytes (Path.Combine (documentsPath, localFilename), data);
InvokeOnMainThread (() => {
new UIAlertView ("Done", "File downloaded and saved", null, "OK", null).Show ();
});
};
var url = new Uri ("_blueway.PDF");
webClient.DownloadDataAsync (url);
}
// Retrieving the URL
var pdfUrl = new Uri("url.pdf"); //enter your PDF path here
// Open PDF URL with device browser to download
Device.OpenUri(pdfUrl);
//First Create Model Class FileDownload
public class FileDownload
{
public string FileUrl { get; set; }
public string FileName { get; set; }
}
//Create a view in xaml file for button on which we need to perform download functionality
<ImageButton BackgroundColor="Transparent" Clicked="DownloadFile_Clicked" x:Name="ImgFileReportDownload_ViewResult" IsVisible="False">
<ImageButton.Source>
<FontImageSource Glyph=""
Color="#1CBB8C"
Size="30"
FontFamily="{StaticResource FontAwesomeSolid}">
</FontImageSource>
</ImageButton.Source>
</ImageButton>
//Created a method in xaml.cs to download File on the click of button
private async void DownloadFile_Clicked(object sender, EventArgs e)
{
var status = await Permissions.CheckStatusAsync<Permissions.StorageWrite>();
if (status == PermissionStatus.Granted)
{
Uri uri = new Uri(fileReportNameViewResult);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
FileDownload fileDownload = new FileDownload();
fileDownload.FileName = filename;
fileDownload.FileUrl = fileReportNameViewResult;
MessagingCenter.Send<FileDownload>(fileDownload, "Download");
}
else
{
status = await Permissions.RequestAsync<Permissions.StorageWrite>();
if (status != PermissionStatus.Granted)
{
await DisplayAlert("Permission Denied!", "\nPlease go to your app settings and enable permissions.", "Ok");
return;
}
}
}
//In MainActivity.cs , create a method
private void MessagingCenter()
{
Xamarin.Forms.MessagingCenter.Subscribe<FileDownload>(this, "Download", (s) =>
{
NotificationID += 4;
var intent = new Intent(this, typeof(Service.DownloadManager));
intent.PutExtra("url", s.FileUrl);
intent.PutExtra("name", s.FileName);
_layout.SetMinimumHeight(3000);
_layout.Bottom = 350; ;
Snackbar.Make(_layout, "Document is Downloading.", Snackbar.LengthShort)
.Show();
StartService(intent);
});
}
//Create a class DownloadManager.cs in Service folder , copy all the below code and paste , just change the Namespace
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace App.Droid.Service
{
[Service]
public class DownloadManager : Android.App.Service
{
AndroidNotificationManager NotificationManager = new AndroidNotificationManager();
public override IBinder OnBind(Intent intent)
{
return null;
}
public override void OnCreate()
{
}
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
Task.Run(() =>
{
int messageId = ++MainActivity.NotificationID;
string url = intent.GetStringExtra("url");
string filename = intent.GetStringExtra("name");
string extension = url.Substring(url.LastIndexOf('.'));
if (!filename.EndsWith(extension))
{
filename += extension;
}
NotificationManager.ScheduleNotification(filename, "", messageId);
String TempFileName = "";
try
{
HttpWebRequest Http = (HttpWebRequest)WebRequest.Create(url);
WebResponse Response = Http.GetResponse();
long length = Response.ContentLength;
var stream = Response.GetResponseStream();
string baseDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
//string baseDir = Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDownloads).AbsolutePath;
//string baseDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
//string baseDir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
baseDir = Path.Combine(baseDir, filename.Substring(filename.LastIndexOf('/') + 1).Replace(' ', '_'));
Directory.CreateDirectory(baseDir);
//string filePath = Path.Combine(documentsPath, name);
if (filename.Length > 18)
{
TempFileName = filename.Substring(0, 18) + "...";
}
else
{
TempFileName = filename;
}
FileInfo fi = new FileInfo(Path.Combine(baseDir, filename.Substring(filename.LastIndexOf('/') + 1).Replace(' ', '_')));
var fis = fi.OpenWrite();
long count = 0;
int begpoint = 0;
bool iscancelled = false;
MessagingCenter.Subscribe<CancelNotificationModel>(this, "Cancel", sender =>
{
if (messageId == sender.ID)
{
iscancelled = true;
}
});
while (true)
{
try
{
if (iscancelled == true)
{
break;
}
// Read file
int bytesRead = 0;
byte[] b = new byte[1024 * 1024];
bytesRead = stream.Read(b, begpoint, b.Length);
if (bytesRead == 0)
break;
fis.Write(b, 0, bytesRead);
fis.Flush();
count += bytesRead;
System.Diagnostics.Debug.WriteLine(count + "-" + length);
if (count >= length)
break;
NotificationManager.ChangeProgress(TempFileName, (int)((count * 100) / length), messageId);
}
catch (Exception ex)
{
Http = (HttpWebRequest)WebRequest.Create(url);
WebHeaderCollection myWebHeaderCollection = Http.Headers;
Http.AddRange(count, length - 1);
Response = Http.GetResponse();
stream = Response.GetResponseStream();
}
}
fis.Close();
NotificationManager.RemoveNotification(messageId);
if (iscancelled == false)
{
new AndroidNotificationManager().DownloadCompleted(filename, "Download Completed", Path.Combine(baseDir, filename), ++messageId);
}
}
catch (Exception ex)
{
NotificationManager.RemoveNotification(messageId);
NotificationManager.FileCancelled(filename, "Download Cancelled, Please try again", ++messageId);
}
});
return StartCommandResult.NotSticky;
}
public override void OnDestroy()
{
}
}
public class CancelNotificationModel
{
public int ID { get; set; }
}
}
//Create a class AndroidNotificationManager.cs in Service folder
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using AndroidX.Core.App;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xamarin.Essentials;
using AndroidApp = Android.App.Application;
namespace App.Droid.Service
{
public class AndroidNotificationManager
{
const string channelId = "default";
const string channelName = "Default";
const string channelDescription = "The default channel for notifications.";
const int pendingIntentId = 0;
public const string TitleKey = "title";
public const string MessageKey = "message";
bool channelInitialized = false;
NotificationManager manager;
NotificationCompat.Builder builder;
public event EventHandler NotificationReceived;
public void Initialize()
{
CreateNotificationChannel();
}
public void RemoveNotification(int messageid)
{
manager.Cancel(messageid);
}
public int ScheduleNotification(string title, string message, int messageId, bool isInfinite = false)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
Intent intent = new Intent(AndroidApp.Context, typeof(MainActivity));
intent.PutExtra(TitleKey, title);
intent.PutExtra(MessageKey, message);
PendingIntent pendingIntent = PendingIntent.GetActivity(AndroidApp.Context, pendingIntentId, intent, PendingIntentFlags.OneShot);
builder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentTitle(title)
.SetContentText(message)
.SetPriority(NotificationCompat.PriorityLow)
.SetVibrate(new long[] { 0L })
.SetProgress(100, 0, isInfinite)
.SetSmallIcon(Resource.Drawable.checkcircle);
var notification = builder.Build();
manager.Notify(messageId, notification);
return messageId;
}
public void ChangeProgress(string filename, int progress, int messageId)
{
try
{
var actionIntent1 = new Intent();
actionIntent1.SetAction("Cancel");
actionIntent1.PutExtra("NotificationIdKey", messageId);
var pIntent1 = PendingIntent.GetBroadcast(Android.App.Application.Context, 0, actionIntent1, PendingIntentFlags.CancelCurrent);
var ProgressBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetSmallIcon(Resource.Drawable.checkcircle)
.SetContentTitle(filename)
.SetVibrate(new long[] { 0L })
.AddAction(Resource.Drawable.checkcircle, "Cancel", pIntent1)
.SetPriority(NotificationCompat.PriorityLow)
.SetProgress(100, progress, false)
.SetContentText(progress + "%")
.SetAutoCancel(false);
System.Diagnostics.Debug.WriteLine(progress);
manager.Notify(messageId, ProgressBuilder.Build());
}
catch
{
}
}
public void DownloadCompleted(string filenametitle, string Message, string filepath, int messageId)
{
try
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
var CompletedBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentTitle(filenametitle)
.SetContentText(Message)
.SetAutoCancel(true)
.SetSmallIcon(Resource.Drawable.checkcircle);
Intent it = OpenFile(filepath, filenametitle);
if (it != null)
{
PendingIntent contentIntent =
PendingIntent.GetActivity(AndroidApp.Context,
pendingIntentId,
it,
PendingIntentFlags.OneShot
);
CompletedBuilder.SetContentIntent(contentIntent);
}
var notification = CompletedBuilder.Build();
manager.Notify(messageId, notification);
}
catch (Exception ex)
{
}
}
public void FileCancelled(string filenametitle, string Message, int messageId)
{
if (!channelInitialized)
{
CreateNotificationChannel();
}
var CompletedBuilder = new NotificationCompat.Builder(AndroidApp.Context, channelId)
.SetContentTitle(filenametitle)
.SetContentText(Message)
.SetAutoCancel(true)
.SetSmallIcon(Resource.Drawable.checkcircle)
.SetDefaults((int)NotificationDefaults.Sound | (int)NotificationDefaults.Vibrate);
var notification = CompletedBuilder.Build();
manager.Notify(messageId, notification);
}
public void ReceiveNotification(string title, string message)
{
}
void CreateNotificationChannel()
{
manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
var channelNameJava = new Java.Lang.String(channelName);
var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Low)
{
Description = channelDescription
};
manager.CreateNotificationChannel(channel);
}
channelInitialized = true;
}
public Intent OpenFile(string filePath, string fileName)
{
try
{
string application = "";
string extension = fileName.Substring(fileName.IndexOf('.'));
switch (extension.ToLower())
{
case ".doc":
case ".docx":
application = "application/msword";
break;
case ".pdf":
application = "application/pdf";
break;
case ".xls":
case ".xlsx":
application = "application/vnd.ms-excel";
break;
case ".jpg":
case ".jpeg":
case ".png":
application = "image/jpeg";
break;
case ".mp4":
application = "video/mp4";
break;
default:
application = "*/*";
break;
}
Java.IO.File file = new Java.IO.File(filePath);
bool isreadable =
file.SetReadable(true);
string ApplicationPackageName = AppInfo.PackageName;
var context = Android.App.Application.Context;
var component = new Android.Content.ComponentName(context, Java.Lang.Class.FromType(typeof(AndroidX.Core.Content.FileProvider)));
var info = context.PackageManager.GetProviderInfo(component, Android.Content.PM.PackageInfoFlags.MetaData);
var authority = info.Authority;
Android.Net.Uri uri = AndroidX.Core.Content.FileProvider.GetUriForFile(Android.App.Application.Context, authority, file);
Intent intent = new Intent(Intent.ActionView);
System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 3 uri done ");
intent.SetDataAndType(uri, application);
intent.AddFlags(ActivityFlags.GrantReadUriPermission);
intent.AddFlags(ActivityFlags.NoHistory);
intent.AddFlags(ActivityFlags.NewTask);
System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 4open file last ");
return intent;
}
catch (Exception ex)
{
Intent it = new Intent();
it.PutExtra("ex", ex.Message);
System.IO.File.AppendAllText((filePath + "backdebug.txt"), System.Environment.NewLine + "Point 4 uri done " + ex.Message);
return it;
}
}
}
}
Here is the sample code to download file in PCL Xamarin from remote server.
I have used PCLStorage library package which is available in Nuget. You just need download and install in your project.
public async void Downloadfile(string Url)
{
try
{
Uri url = new Uri(Url);
var client = new HttpClient();
IFolder rootfolder = FileSystem.Current.LocalStorage;
IFolder appfolder = await rootfolder.CreateFolderAsync("Download", CreationCollisionOption.OpenIfExists);
IFolder dbfolder = await appfolder.CreateFolderAsync("foldername", CreationCollisionOption.OpenIfExists);
IFile file = await dbfolder.CreateFileAsync(strReport_name, CreationCollisionOption.ReplaceExisting);
using (var fileHandler = await file.OpenAsync(PCLStorage.FileAccess.ReadAndWrite))
{
var httpResponse = await client.GetAsync(url);
byte[] dataBuffer = await httpResponse.Content.ReadAsByteArrayAsync();
await fileHandler.WriteAsync(dataBuffer, 0, dataBuffer.Length);
}
}
catch (Exception ex)
{
throw ex;
}
}
This is driving me crazy. I wrote a code quite a while ago that was working, and opened it again and it happens that I am not able to transfer my assets from the mobile to the wearable device.
public Bitmap loadBitmapFromAsset(Asset asset) {
if (asset == null) {
throw new IllegalArgumentException("Asset must be non-null");
}
// convert asset into a file descriptor and block until it's ready
Log.d(TAG, "api client" + mApiClient);
DataApi.GetFdForAssetResult result = Wearable.DataApi.getFdForAsset(mApiClient, asset).await();
if (result == null) {
Log.w(TAG, "getFdForAsset returned null");
return null;
}
if (result.getStatus().isSuccess()) {
Log.d(TAG, "success");
} else {
Log.d(TAG, result.getStatus().getStatusCode() + ":" + result.getStatus().getStatusMessage());
}
InputStream assetInputStream = result.getInputStream();
if (assetInputStream == null) {
Log.w(TAG, "Requested an unknown Asset.");
return null;
}
// decode the stream into a bitmap
return BitmapFactory.decodeStream(assetInputStream);
}
And this is the code from which I call the loadBitmapFrom Asset method.
DataMap dataMap = DataMapItem.fromDataItem(event.getDataItem()).getDataMap();
ArrayList<DataMap> dataMaps = dataMap.getDataMapArrayList("dataMaps");
ArrayList<String> names = new ArrayList<>();
ArrayList<String> permalinks = new ArrayList<>();
ArrayList<Asset> images = new ArrayList<>();
for (int i = 0 ; i < dataMaps.size() ; i++) {
Log.d(TAG, dataMaps.get(i).getString("name"));
names.add(dataMaps.get(i).getString("name"));
permalinks.add(dataMaps.get(i).getString("permalink"));
images.add(dataMaps.get(i).getAsset("image"));
}
editor.putInt("my_selection_size", names.size());
for (int i=0; i <names.size() ; i++) {
editor.putString("my_selection_name_" + i, names.get(i));
editor.putString("my_selection_permalink_" + i, permalinks.get(i));
Log.d(TAG, "asset number " + i + " " + images.get(i));
Bitmap bitmap = loadBitmapFromAsset(images.get(i));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
String encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
editor.putString("my_selection_image_" + i, encoded);
}
And on the mobile side :
private void sendData(PutDataMapRequest dataMap) {
PutDataRequest request = dataMap.asPutDataRequest();
request.setUrgent();
com.google.android.gms.common.api.PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(mApiClient, request);
pendingResult.setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
#Override
public void onResult(DataApi.DataItemResult dataItemResult) {
com.orange.radio.horizon.tools.Log.d(TAG, "api client : " + mApiClient);
if (dataItemResult.getStatus().isSuccess()) {
com.orange.radio.horizon.tools.Log.d(TAG, "message successfully sent");
} else if (dataItemResult.getStatus().isInterrupted()) {
com.orange.radio.horizon.tools.Log.e(TAG, "couldn't send data to watch (interrupted)");
} else if (dataItemResult.getStatus().isCanceled()) {
com.orange.radio.horizon.tools.Log.e(TAG, "couldn't send data to watch (canceled)");
}
}
});
Log.d(TAG, "Sending data to android wear");
}
class ConfigTask extends AsyncTask<String, Void, String> {
ArrayList<WatchData> mitems;
int mType;
public ConfigTask(ArrayList<WatchData> items, int type)
{
mitems = items;
mType = type;
}
protected String doInBackground(String... str)
{
DataMap dataMap;
ArrayList<DataMap> dataMaps = new ArrayList<>();
Bitmap bitmap = null;
for (int i = 0 ; i < mitems.size() ; i++) {
dataMap = new DataMap();
URL url = null;
try {
url = new URL(mitems.get(i).mUrlSmallLogo);
Log.d(TAG, "url : " + url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
Asset asset = createAssetFromBitmap(bitmap);
dataMap.putAsset("image", asset);
dataMap.putString("name", mitems.get(i).mName);
dataMap.putString("permalink", mitems.get(i).mPermalink);
dataMaps.add(dataMap);
}
PutDataMapRequest request = null;
switch (mType) {
case 0 :
request = PutDataMapRequest.create(SELECTION_PATH);
break;
case 1 :
request = PutDataMapRequest.create(RADIOS_PATH);
break;
case 2 :
request = PutDataMapRequest.create(PODCASTS_PATH);
break;
}
request.getDataMap().putDataMapArrayList("dataMaps", dataMaps);
request.getDataMap().putString("", "" + System.currentTimeMillis()); //random data to refresh
Log.d(TAG, "last bitmap : " + bitmap);
Log.d(TAG, "===============================SENDING THE DATAMAP ARRAYLIST==================================");
sendData(request);
return "h";
}
protected void onPostExecute(String name)
{
}
}
When executing that code, I see the following error happening :
02-02 14:47:59.586 7585-7601/? D/WearMessageListenerService﹕ 4005:ASSET_UNAVAILABLE
I saw that related thread Why does Wearable.DataApi.getFdForAsset produce a result with status 4005 (Asset Unavailable)? but it didn't really help me
I recently had the same problem... I solved it by updating the Google play service, and adding the same signing configuration to both the app and the wearable module. If it doesn't work on the first build go to "invalidate caches / restart" in files and it should work.
i am trying to integrate qr code scanner in my application in android, i am using zxing library BarcodeEye.
i have implemented below piece of code
Intent intent = new Intent("com.github.barcodeeye.scan.CaptureActivity");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
but i am getting a RuntimeException saying that unable to start activity component : android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.github.barcodeeye.scan}
can any one help me where i am going wrong
Thanks & Regards.
Nagendra
You will need to register CaptureActivity Activity in the AndroidManifest.xml
<activity
android:name="com.github.barcodeeye.scan.CaptureActivity"
android:clearTaskOnLaunch="true"
android:configChanges="orientation|keyboardHidden"
android:screenOrientation="landscape"
android:stateNotNeeded="true"
android:theme="#style/CaptureTheme"
android:windowSoftInputMode="stateAlwaysHidden" >
<intent-filter>
<action android:name="com.github.barcodeeye.SCAN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Here is how I use BarCodeEye:
private void startScanActivityForResult(Bundle extras)
{
Intent intentScan = new Intent("com.github.barcodeeye.SCAN");
intentScan.setPackage("com.github.barcodeeye");
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
intentScan.putExtras(extras);
intentScan.putExtra("SCAN_MODE", "QR_CODE_MODE");
intentScan.putExtra("RESULT_DISPLAY_DURATION_MS", 1000L);
intentScan.putExtra("SAVE_HISTORY", false);
intentScan.putExtra("PROMPT_MESSAGE", "QR scan http://user:pass#server");
WtcLog.info(TAG, "startScanActivityForResult: startActivityForResult(intentScan=" + intentScan + ", REQUEST_SCAN)");
startActivityForResult(intentScan, REQUEST_SCAN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
WtcLog.info(TAG, "onActivityResult data=" + WtcUtilsPlatform.toString(data));
Bundle extras = null;
if (data != null)
{
extras = data.getExtras();
}
switch (requestCode)
{
case REQUEST_SCAN:
{
WtcLog.info(TAG, "onActivityResult: REQUEST_SCAN");
if (resultCode == RESULT_OK)
{
WtcLog.info(TAG, "onActivityResult: resultCode == RESULT_OK");
String result = data.getStringExtra("SCAN_RESULT");
extras = validateScan(result);
/// your logic here
}
else
{
WtcLog.warn(TAG, "onActivityResult: resultCode != RESULT_OK; exiting");
// your logic here
finish();
}
break;
}
}
}
private Bundle validateScan(String result)
{
Bundle extras = new Bundle();
String[] userpass;
try
{
URI uri = new URI(result);
String userinfo = uri.getRawUserInfo();
if (WtcString.isNullOrEmpty(userinfo))
{
throw new URISyntaxException(result, "");
}
userpass = userinfo.split(":", 2);
if (userpass.length != 2)
{
throw new URISyntaxException(result, "");
}
String server = uri.getHost();
if (WtcString.isNullOrEmpty(server))
{
throw new URISyntaxException(result, "");
}
extras.putString("server", server);
}
catch (URISyntaxException e)
{
WtcLog.error(TAG, "validateScan: EXCEPTION", e);
extras.putString("error", "uri must be in format \"http://username:password#server\"");
return extras;
}
try
{
String username = URLDecoder.decode(userpass[0], "UTF-8");
extras.putString("username", username);
String password = URLDecoder.decode(userpass[1], "UTF-8");
extras.putString("password", password);
}
catch (UnsupportedEncodingException e)
{
WtcLog.error(TAG, "validateScan: EXCEPTION", e);
extras.putString("error", "username and password must be UTF-8");
return extras;
}
return extras;
}
What I want to do is simply to upload a photo to a webservice using mono touch/mono droid and mvvmcross, hopefully in a way so I only have to write the code once for both android and IOS :)
My initial idea is to let the user pick an image (in android using an intent) get the path for the image. Then use MvxResourceLoader resourceLoader to open an stream from the path and then use restsharp for creating a post request with the stream.
However I already hit a wall, when the user picks an image the path is e.g. "/external/images/media/13". this path results in a file not found exception when using the MvxResourceLoader resourceLoader.
Any ideas to why I get the exception or is there an better way to achieve my goal?
This is how I ended up doinging it - thank you stuart and to all the links :)
public class PhotoService :IPhotoService, IMvxServiceConsumer<IMvxPictureChooserTask>,IMvxServiceConsumer<IAppSettings>
{
private const int MaxPixelDimension = 300;
private const int DefaultJpegQuality = 64;
public void ChoosePhotoForEventItem(string EventGalleryId, string ItemId)
{
this.GetService<IMvxPictureChooserTask>().ChoosePictureFromLibrary(
MaxPixelDimension,
DefaultJpegQuality,
delegate(Stream stream) { UploadImage(stream,EventGalleryId,ItemId); },
() => { /* cancel is ignored */ });
}
private void UploadImage(Stream stream, string EventGalleryId, string ItemId)
{
var settings = this.GetService<IAppSettings>();
string url = string.Format("{0}/EventGallery/image/{1}/{2}", settings.ServiceUrl, EventGalleryId, ItemId);
var uploadImageController = new UploadImageController(url);
uploadImageController.OnPhotoAvailableFromWebservice +=PhotoAvailableFromWebservice;
uploadImageController.UploadImage(stream,ItemId);
}
}
public class PhotoStreamEventArgs : EventArgs
{
public Stream PictureStream { get; set; }
public Action<string> OnSucessGettingPhotoFileName { get; set; }
public string URL { get; set; }
}
public class UploadImageController : BaseController, IMvxServiceConsumer<IMvxResourceLoader>, IMvxServiceConsumer<IErrorReporter>, IMvxServiceConsumer<IMvxSimpleFileStoreService>
{
public UploadImageController(string uri)
: base(uri)
{
}
public event EventHandler<PhotoStreamEventArgs> OnPhotoAvailableFromWebservice;
public void UploadImage(Stream stream, string name)
{
UploadImageStream(stream, name);
}
private void UploadImageStream(Stream obj, string name)
{
var request = new RestRequest(base.Uri, Method.POST);
request.AddFile("photo", ReadToEnd(obj), name + ".jpg", "image/pjpeg");
//calling server with restClient
var restClient = new RestClient();
try
{
this.ReportError("Billedet overføres", ErrorEventType.Warning);
restClient.ExecuteAsync(request, (response) =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
//upload successfull
this.ReportError("Billedet blev overført", ErrorEventType.Warning);
if (OnPhotoAvailableFromWebservice != null)
{
this.OnPhotoAvailableFromWebservice(this, new PhotoStreamEventArgs() { URL = base.Uri });
}
}
else
{
//error ocured during upload
this.ReportError("Billedet kunne ikke overføres \n" + response.StatusDescription, ErrorEventType.Warning);
}
});
}
catch (Exception e)
{
this.ReportError("Upload completed succesfully...", ErrorEventType.Warning);
if (OnPhotoAvailableFromWebservice != null)
{
this.OnPhotoAvailableFromWebservice(this, new PhotoStreamEventArgs() { URL = url });
}
}
}
//method for converting stream to byte[]
public byte[] ReadToEnd(System.IO.Stream stream)
{
long originalPosition = stream.Position;
stream.Position = 0;
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
stream.Position = originalPosition;
}
}
}
Try:
Issues taking images and showing them with MvvmCross on WP
Need an example of take a Picture with MonoDroid and MVVMCross
https://github.com/Redth/WshLst/ - uses Xam.Mobile for it's picture taking