CreateChooser is not working in Android v5.1 - xamarin

I am using intent to share pdf files. I am restricting apps when share file. I want to share the file to Good document, Kindle and drop box alone. I am using the below code to achieve this.But the below code is not working in android v5.1. The device have the required app to share. But it is showing "No apps can perform this action" when share. Can you anyone suggest your ideas to resolve this?
var pathFile = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
var m_documentMobiNames = shortName + "." + fileType;
var mobileFileName = Path.Combine(pathFile, m_documentMobiNames);
var shareIntentsLists = new List<Intent>();
Intent sendIntent = new Intent();
sendIntent.SetAction(Intent.ActionSend);
sendIntent.SetType("application/pdf");
var resInfos = context.PackageManager.QueryIntentActivities(sendIntent, 0);
if (resInfos.Count > 0)
{
foreach (var resInfo in resInfos)
{
string packageName = resInfo.ActivityInfo.PackageName;
if (packageName.Contains("com.google.android.apps.docs") || packageName.Contains("com.dropbox.android") || packageName.Contains("com.amazon.kindle"))
{
Intent intent = new Intent();
intent.SetComponent(new ComponentName(packageName, resInfo.ActivityInfo.Name));
intent.SetAction(Intent.ActionSend);
intent.SetType("application/pdf");
intent.PutExtra(Intent.ExtraStream, Android.Net.Uri.Parse("file://" + mobileFileName));
intent.SetPackage(packageName);
shareIntentsLists.Add(intent);
}
}
}
if (shareIntentsLists.Count > 0)
{
chooserIntent = Intent.CreateChooser(new Intent(), "Share with");
chooserIntent.PutExtra(Intent.ExtraStream, Android.Net.Uri.Parse(mobileFileName));
chooserIntent.PutExtra(Intent.ExtraInitialIntents, shareIntentsLists.ToArray());
chooserIntent.SetFlags(ActivityFlags.ClearTop);
chooserIntent.SetFlags(ActivityFlags.NewTask);
context.StartActivity(chooserIntent);
await Task.FromResult(true);
}

Related

Error comparing current app version number with latest. Version name=production.release.1.0.0.5 and lastest version= [duplicate]

I need to check current version of Installed Application and Playstore application version. If it is not same app should navigate to Playstore .
im using xam.Plugin.LatestVersion(2.1.0) To get the latestversion number of application from play console. unfortunately not getting latest version number of application from play store. The below code im using.
private async void ChekAppVersion()
{
try
{
latestVersionNumber = await CrossLatestVersion.Current.GetLatestVersionNumber();
installedVersionNumber = CrossLatestVersion.Current.InstalledVersionNumber;
if (installedVersionNumber != latestVersionNumber)
{
await DisplayAlert("New Version", "There is a new version of this app available. Please update now?", "Ok");
await CrossLatestVersion.Current.OpenAppInStore();
ChekAppVersion();
}
else
{
}
}
catch (Exception ex)
{
}
}
Im getting the installedVersionNumber, but im unable to get the latestVersionNumber(Playstore).
Please help on this.
They have removed the version from div, now it's displayed with js, but data is still there inside a <script> tag. My current fixed code is:
private bool _lockCheckUpdates;
public async Task<bool> CheckNeedUpdate()
{
if (Connectivity.NetworkAccess != NetworkAccess.Internet || _lockCheckUpdates)
return false;
_lockCheckUpdates = true;
try
{
HttpClient myClient = CreateClient();
if (Device.RuntimePlatform == Device.Android)
{
var bundle = "com.todo.app"; //ANDROID BUNDLE NAME HERE
string url = $"https://play.google.com/store/apps/details?id={bundle}&hl=en";
string raw = await myClient.GetStringAsync(new Uri(url));
var doc = new HtmlDocument();
doc.LoadHtml(raw);
var scripts = doc.DocumentNode.Descendants()
.Where(n => n.Name == "script" && n.InnerText.Contains("AF_initDataCallback({key: 'ds:4'"))
.ToArray();
var script = scripts.First().InnerText;
var engine = new Jurassic.ScriptEngine();
var eval = "(function() { var AF_initDataCallback = function(p) { return p.data[1][2][140][0][0][0]; }; return " + script + " })()";
var result = engine.Evaluate(eval);
//var json = JSONObject.Stringify(engine, result); //for debug, check in browser console with JSON.parse(json)
var remote = $"{result}".ToDouble();
var local = App.Version.ToDouble();
return local < remote;
}
else if (Device.RuntimePlatform == Device.iOS)
{
var bundle = "com.todo.app";//iOS BUNDLE NAME HERE
string url = $"http://itunes.apple.com/lookup?bundleId={bundle}";
string raw = await myClient.GetStringAsync(new Uri(url));
var dto = JsonConvert.DeserializeObject<AppStoreRecord>(raw);
double local = App.Version.ToDouble();
if (dto.ResultCount > 0)
{
double remote = dto.Results[0].Version.ToDouble();
return remote > local;
}
}
}
catch (Exception e)
{
Logger.Error("CheckNeedUpdate", e);
}
finally
{
_lockCheckUpdates = false;
}
return false;
}
Using nugets
Jurassic to evaluate the script on page,
HtmlAgilityPack to parse html,
Xamarin.Essentials to check if we are online,
and AppoMobi.Specials for .ToDouble() etc
I hope this could also be useful to fix https://github.com/edsnider/latestversionplugin/issues/43 :)
The plugin you are using no longer works for Android https://github.com/edsnider/latestversionplugin/issues/43
You will need to find a new way to get the desired information.
PR has been made on this plugin... it works again ;-)

Slash xamarin issue

I am trying to get values from a specified route to load it in a collectionView. I don't know why Xamarin add a / to my path at the beggining. I am desesperate, I've tried to replace the /, differents ways to obtain the path, in differents places (inside the project, in the desktop) and any works. I think the problem could be the MonoAndroid file or some dll but I am not sure.
Differents things I've tried:
1:
StreamReader sr = new StreamReader("./ficheroPruebaXautoCB.txt");
string linea;
// Read the file and display it line by line.
while ((linea = sr.ReadLine()) != null)
{
ubicaciones.Ubication = linea.Substring(27, 33);
ubicaciones.Values = linea.Substring(0, 26) + linea.Substring(34, 48);
listUbicaciones.Add(ubicaciones);
counter++;
}
sr.Close();
2:
string path = "F:\\Xamarin\\Pruebas_fichero\\ficheroPruebaXautoCB.txt";
string path2 = #"F:\Xamarin\Pruebas_fichero\ficheroPruebaXautoCB.txt";
foreach (string line in System.IO.File.ReadLines(path2))
{
ubicaciones.Ubication = line.Substring(27, 33);
ubicaciones.Values = line.Substring(0, 26) + line.Substring(34, 48);
listUbicaciones.Add(ubicaciones);
counter++;
}
3:
string nombreArchivo = "ficheroPruebaXautoCB.txt";
string ruta = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
string rutaCompleta = Path.Combine(ruta, nombreArchivo);
if (File.Exists(rutaCompleta))
{
using (var lector = new StreamReader(rutaCompleta, true))
{
string textoLeido;
while ((textoLeido = lector.ReadLine()) != null)
{
ubicaciones.Ubication = textoLeido.Substring(27, 33);
ubicaciones.Values = textoLeido.Substring(0, 26) + textoLeido.Substring(34, 48);
listUbicaciones.Add(ubicaciones);
counter++;
}
}
}
4:
string ruta = "C:\\Users\\H_L\\Desktop\\ficheroPruebaXautoCB.txt";
try
{
//FileStream f = File.OpenRead(ruta);
var text = File.ReadLines(ruta, Encoding.UTF8);
foreach (string line in text)
{
ubicaciones.Ubication = line.Substring(27, 33);
ubicaciones.Values = line.Substring(0, 26) + line.Substring(34, 48);
listUbicaciones.Add(ubicaciones);
}
}
catch (IOException e)
{
Console.WriteLine(e.Message);
}
And the error:
"Could not find file "/C:\Users\H_L\Desktop\ficheroPruebaXautoCB.txt""
All these solutions have worked in a console C# project, so the problem is when I try to do it with Xamarin.
It seems that you can't access the file in your pc with the path for the android. You need to provide a path which the Android can use.
At first, you need to copy the local file into the simulator. You can check the following link : How to access local files of the filesystem in the Android emulator?
And then, if the file is in the app's own folder, you can access it without any storage permission. But when the file is in the other folders, you need to grant the read and write storage permission to your app.
You can check my old answer in the following link:How to open SQLite DB created by one Xamarin Android app in another app?

How to get a device's serial no with Nativescript?

Does anybody know how to get the serial number of a device?
I know I can do this in a NativeScript-5 application (TypeScript):
import { Page } from "tns-core-modules/ui/page";
import * as platformModule from "tns-core-modules/platform";
export function onNavigatingTo(args: EventData) {
let page = <Page>args.object;
console.log("Manufacturer:" + platformModule.device.manufacturer);
console.log("Model:" + platformModule.device.model);
console.log("UUID:" + platformModule.device.uuid);
}
But I couldnt find any property for the device's serial number.
Anybody an idea? It's alright if your solution only covers Android (since my project is targeting Android tablets only).
Thanks!
Update:
Manoj pointed me to some Java code that probably solves my problem. However, I wasn't able to marshal the following code to TypeScript.
public static String getManufacturerSerialNumber() {
String serial = null;
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class, String.class);
serial = (String) get.invoke(c, "ril.serialnumber", "unknown");
} catch (Exception ignored) {}
return serial;
}
Maybe anybody could help me? That would be awesome!
iOS never allows any confidential information to be accessed by apps, that applies to serial number too. With Android, you may read the serial number with
android.os.Build.SERIAL
I had it tested with Playground
Edit 1:
Manufactures like Samsung seems to have a different serial number which is not same as android.os.Build.SERIAL. Here is another SO thread that seems very relevant for Samsung, the sample code is written in Java.
Edit 2:
Here is how you may get serial number on Samsung devices
let serialNumber = '';
try {
const cl = application.android.context.getClassLoader();
const SystemProperties = cl.loadClass('android.os.SystemProperties');
const paramTypes = (<any>Array).create(java.lang.Class, 2);
paramTypes[0] = java.lang.String.class;
paramTypes[1] = java.lang.String.class;
const getMethod = SystemProperties.getMethod('get', paramTypes);
const params = (<any>Array).create(java.lang.Object, 2);
params[0] = new java.lang.String('ril.serialnumber');
params[1] = new java.lang.String('unknown');
serialNumber = getMethod.invoke(SystemProperties, params);
} catch (err) {
console.error(err);
}
Updated Playground
You can check properties 'ro.serialno', 'ril.serialnumber', 'gsm.sn1', 'sys.serialnumber'
Android: How to programmatically access the device serial number shown in the AVD manager (API Version 8)
In my case Samsung TAB S2 has 2 serials. Property 'ro.serialno' more accurate then 'ril.serialnumber'. So i check it first.
getSerial() {
if (isAndroid) {
let serialNumber = null;
try {
const cl = application.android.context.getClassLoader();
const SystemProperties = cl.loadClass('android.os.SystemProperties');
const paramTypes = (<any>Array).create(java.lang.Class, 2);
paramTypes[0] = java.lang.String.class;
paramTypes[1] = java.lang.String.class;
const getMethod = SystemProperties.getMethod('get', paramTypes);
const params = (<any>Array).create(java.lang.Object, 2);
// Reorder if needed
const props = ['ro.serialno', 'ril.serialnumber', 'gsm.sn1', 'sys.serialnumber'];
for(let i = 0, len = props.length; i < len; i++) {
params[0] = new java.lang.String(props[i]);
serialNumber = getMethod.invoke(SystemProperties, params);
if (serialNumber !== '') {
return serialNumber;
}
}
} catch (err) {
console.error(err);
}
return serialNumber;
}
}
Full code: https://play.nativescript.org/?template=play-tsc&id=ViNo6g&v=6

Android post image to Facebook comment

This is a followup to my previous question: Xamarin.Forms App return data to calling App
That works perfectly and I can share images to anywhere, except to Facebook comments. When I click the camera on the content box the app can be selected, I can select the image, Set result and Finish are called, and the app closes and it sends data to Facebook, and then however I then get the error : The image could not be uploaded, try again?
I can't find any fundamental differences between posting to a status or a comment, so I'm guessing it's subtle. Any thoughts on how I can change my intent to post properly?
Adding for completeness:
Bitmap b = null;
string url;
if (!string.IsNullOrEmpty(this.saleItems[i].ImageUrl))
{
url = this.saleItems[i].ImageUrl;
}
else
{
url = await FileHelper.GetLocalFilePathAsync(this.saleItems[i].Id);
}
//download
using (var webClient = new WebClient())
{
var imageBytes = webClient.DownloadData(url);
if (imageBytes != null && imageBytes.Length > 0)
{
b = BitmapFactory.DecodeByteArray(imageBytes, 0, imageBytes.Length);
}
}
//set local path
var tempFilename = "test.png";
var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;
var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);
using (var os = new FileStream(filePath, FileMode.Create))
{
b.Compress(Bitmap.CompressFormat.Png, 100, os);
}
b.Dispose();
var imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");
var sharingIntent = new Intent();
sharingIntent.SetAction(Intent.ActionSend);
sharingIntent.SetType("image/*");
sharingIntent.PutExtra(Intent.ExtraText, "some txt content");
sharingIntent.PutExtra(Intent.ExtraStream, imageUri);
sharingIntent.AddFlags(ActivityFlags.GrantReadUriPermission);
//await SaleItemDataService.Instance.BuySaleItemAsync(this.saleItem);
SetResult(Result.Ok, sharingIntent);
Finish();
Use below:
Intent sharingIntent = new Intent();
string imageUri = "file://" + requestedUri;
sharingIntent.SetData(Android.Net.Uri.Parse(imageUri));

Image Upload doesn't work in Server. Works fine in localhost

So, this code works just fine in localhost. It deletes the previous image and uploads the new one. It does nothing on server however. Any clue?
I have used AJAX for asynchorous call By the way if that makes a difference.
var db=Database.Open("StarterSite");
var contentQuery="Select * from Contents where id =#0";
var content=db.QuerySingle(contentQuery,"1");
var message="";
var imgCount=0;
var alreadyExist=false;
try{
if (IsPost && Request.Files.Count > 0) {
bool deleteSuccess = false;
var fileName = "";
var photoName = "";
var fileSavePath = "";
var uploadedFile = Request.Files[0];
var toDelete=Request["toDelete"];
var toUpload=Request["toUpload"];
if(uploadedFile.ContentLength>0){
#******************DELETE***************#
var fullPath = Server.MapPath("~/img/" + toDelete);
if (File.Exists(fullPath))
{
File.Delete(fullPath);
deleteSuccess = true;
}
#****************UPLOAD*******************#
fileName = Path.GetFileName(uploadedFile.FileName);
fileSavePath = Server.MapPath("~/img/" +
fileName);
uploadedFile.SaveAs(fileSavePath);
var updateQuery="Update Contents Set "+toUpload +"=#0";
db.Execute(updateQuery, fileName);
//Response.Redirect("editMode.cshtml");
}
}
}
catch(HttpException ex){
message="Image size you selected was too large. Please select a different Image.";
}
Try changing the permission of the folder to 777.

Resources