How to use SetAction in Xamarin - c#

I'm trying to whitelist my app on Android 6.0 or greater. I have seen Android code to do this, but it doesn't translate in Xamarin and Xamarin documentation only tells you that SetAction takes a string as an argument, and then a link to Android documentation which doesn't end up being the same.
Here's the Android code that Xamarin will not accept
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
It doesn't like Settings. I've read the Xamarin documentation which says that SetAction() takes a string arg, and that's all they say and point you to Android documentation.
Note, I am calling this in a javascript interface class and I tried this but it doesn't work
class MyJSInterface : Java.Lang.Object
{
Context context;
public MyJSInterface(Context context)
{
this.context = context;
}
[Export]
[JavascriptInterface]
public void SetDozeOptimization()
{
Toast.MakeText(context, "launch optimization", ToastLength.Short).Show();
setDozeComplete = false;
Intent intent = new Intent();
String packageName = context.PackageName;
PowerManager pm = (PowerManager)context.GetSystemService(Context.PowerService);
if (pm.IsIgnoringBatteryOptimizations(packageName))
intent.SetAction("ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS");
else
{
intent.SetAction("ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS");
intent.SetData(Android.Net.Uri.Parse("package:" + packageName));
}
context.StartActivity(intent);
}
}
So what is the correct syntax to accomplish this?

Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations:
android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
Android.Provider.Settings.ActionIgnoreBatteryOptimizationSettings:
android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS
Example:
intent.SetAction(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations);
intent.SetAction(Android.Provider.Settings.ActionIgnoreBatteryOptimizationSettings);

Here is the code you are looking for:
Intent intent = new Intent();
String packageName = context.PackageName;
PowerManager pm(PowerManager)Android.App.Application.Context.GetSystemService(Context.PowerService);
if (!pm.IsIgnoringBatteryOptimizations(packageName))
{
intent.SetAction(Android.Provider.Settings.ActionRequestIgnoreBatteryOptimizations);
intent.SetData(Android.Net.Uri.Parse("package:" + packageName));
StartActivity(intent);
}

Related

Xamarin forms not updating notifications changes on final APK

I have a Xamarin Forms project where I use the following notifications code for Android:
[Service(Exported = false)]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
string messageTitle = GetTitle(message);
string messageBody = GetBody(message);
// convert the incoming message to a local notification
ConfigureAndSendLocalNotification(messageTitle, messageBody);
}
private void ConfigureAndSendLocalNotification(string title, string body)
{
NotificationCompat.Builder notificationBuilder = ConfigureNotificationBuilder(title, body);
SendNotification(notificationBuilder);
}
private NotificationCompat.Builder ConfigureNotificationBuilder(string title, string body)
{
Intent intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
intent.PutExtra("title", title);
intent.PutExtra("message", body);
PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.Immutable);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, Util.Constants.NotificationChannelName)
...//configuring notification
return notificationBuilder;
}
I'm trying to modify this code to give users a better experience. However, when i generate the APK (going to archive -> distribute -> save as), it seems not to recognize any change in this file.
I've actually commented this part of the code:
public override void OnMessageReceived(RemoteMessage message){
//base.OnMessageReceived(message);
string messageTitle = GetTitle(message);
string messageBody = GetBody(message);
// convert the incoming message to a local notification
//ConfigureAndSendLocalNotification(messageTitle, messageBody);
}
And the notification keeps appearing on the generated APK when I run it on my Android.
Creepy detail: In the Android emulator, all of my changes are correctly displayed. They really are just not reflected in the final APK.
Any ideas?

Toast Notifications not working on XF Android 8.0/1

I have a cross platform XF app.
I am using Toast.Forms for sending local app notifications, the plugin works on both iOS and Android.
On iOS it works perfectly fine, but on Android it works only for versions lower than 7.1, for oreo 8.0 or 8.1 (> API 26) it does not work anymore.
Here is my toast class:
internal class ToastService : IToastService
{
private readonly IAppDeviceDependency _DeviceDependency;
public ToastService([NotNull] IAppDeviceDependency deviceDependency)
{
_DeviceDependency = deviceDependency ?? throw new ArgumentNullException(nameof(deviceDependency));
}
public void ShowToast(string title, string description, bool isClickable, bool clearFromHistory)
{
DeviceToastProvider.ShowToast(title, description, isClickable, clearFromHistory);
}
private IToastProvider DeviceToastProvider => _DeviceDependency.Get<IToastProvider>();
}
Android toast provider:
[assembly: Dependency(typeof(AndroidToastProvider))]
namespace MyApp.Droid.Providers
{
public class AndroidToastProvider : IToastProvider
{
public async void ShowToast(string title, string description, bool isClickable, bool clearFromHistory)
{
var notificator = DependencyService.Get<IToastNotificator>();
await notificator.Notify(new NotificationOptions
{
Title = title,
Description = description,
IsClickable = isClickable,
ClearFromHistory = clearFromHistory
});
}
}
}
Apple toast provider
[assembly: Dependency(typeof(AppleToastProvider))]
namespace MyApp.iOS.Providers
{
public class AppleToastProvider : IToastProvider
{
public async void ShowToast(string title, string description, bool isClickable, bool clearFromHistory)
{
var notificator = DependencyService.Get<IToastNotificator>();
await notificator.Notify(new NotificationOptions
{
Title = title,
Description = description,
IsClickable = isClickable,
ClearFromHistory = clearFromHistory
});
}
}
}
Android 8 requires notifications to have a channel assigned to them to be displayed (see more here: https://developer.android.com/guide/topics/ui/notifiers/notifications). If your plugin doesn't support that you can ask the authors to update it in a proper way or you can create your own code using native APIs.
Found the solution to the problem. Apparently I was compiling using Android version 7.1, which does not support the newly Notification Channel of the Android Oreo 8.0. Now I am compiling using Android 8.1 (Oreo), I have updated Toast.plugin to the latest version and it works perfectly fine on all versions lowers than Android 8.1
More on the issue can be found here: https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/notifications/local-notifications

Xamarin c# Intent error with typeof(broadcasterclass)

Hi I try to build an alarm clock in Xamarin Forms. When I try to make an Intent(in Android) then some errors come during the runtime.
My ClockAndroid class where i call the Intent:
[assembly: Dependency(typeof(ClockAndroid))]
namespace AlarmClock.Droid
{
class ClockAndroid : IClock
{
public void SetAlarm()
{
var intent = new Intent(Android.App.Application.Context, typeof(AlarmBroadcast));
var source = PendingIntent.GetBroadcast(Android.App.Application.Context, 0, intent, 0);
// Schedule the alarm for 30 se+conds from now!
var am = (AlarmManager)Android.App.Application.Context.GetSystemService(Context.AlarmService);
am.Set(AlarmType.ElapsedRealtime, SystemClock.ElapsedRealtime() + 5 * 1000, source);
}
}
}
My BroadcastReceiver (AlarmBroadcast):
namespace Wecker.Droid
{
[BroadcastReceiver]
public class AlarmBroadcast : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
// do something
}
}
}
The Error is here:
var intent = new Intent(Android.App.Application.Context, typeof(AlarmBroadcast));
ErrorMessage:
Unhandled Exception:
System.Reflection.TargetInvocationException: <Timeout exceeded getting exception details>
The problem is not the code...
I have debuged with xamarin live player and an android simulator.
The solution is to put it on a real device.

Xamarin Forms Webview local

I am trying to load a Web application (Readium) in a webview with Xamarin locally. As a target I have UWP, Android and iOS.
I can not get the index.html page open, I have embedded the web in each of the projects, according to https://developer.xamarin.com/guides/xamarin-forms/user-interface/webview/ but I get a blank page.
have implemented the dependency service for each application such as (UWP)
assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
public class BaseUrl : IBaseUrl
{
public string Get()
{
return "ms-appx-web:///";
}
}
}
However, creating a new UWP project (without Xamarin), it works well, using the method NavigateToLocalStreamUri(uri, new StreamUriWinRTResolver()) with
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath; 
return GetContent(path).AsAsyncOperation();
}
private async Task<IInputStream> GetContent(string path)
{  
try
{
Uri localUri = new Uri("ms-appx:///cloud-reader" + path);
StorageFile f = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await f.OpenAsync(FileAccessMode.Read);
return stream;
}
catch (Exception)
{
throw new Exception("Invalid path");
}
}
In what way would the same be done in Xamarin Forms?
Thanks you.
Finally I achieve to load local content adding a custom render for each platform.
Example (UWP):
[assembly: ExportRenderer(typeof(WebView), typeof(WebViewRenderer))]
namespace DisplayEpub.UWP{
public class CustomWebViewRenderer : WebViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var customWebView = Element as WebView;
Control.Source = new Uri(string.Format("ms-appx-web:///Assets/pdfjs/web/viewer.html"));
}
}
}
}
I've followed the example of Xamarin docs to display PDF using custom render, targeting 3 platforms. I've tested it on Android and Windows:
https://developer.xamarin.com/recipes/cross-platform/xamarin-forms/controls/display-pdf/

How to save accesstoken to string from API (C# Xamarin Studio)

I just started learning programming and I am currently trying out developing an android mobile application. I have watched a lot of tutorials and trying to find solutions online, but i can’t seem to get a hang of it.
So i am now reaching out to you guys for some help.
I am working in Xamarin Studio, C#, and I am trying to create a loginsystem with the help of a REST API, and i am not really sure how i save the accesstoken to a string so that i can use it in further requests.
FILE: MainActivity.cs
namespace APItest

{
[Activity(Label = "APItest", MainLauncher = true)]
public class MainActivity : Activity

{

private WebClient mClient;
private Uri mUrl;
private List<string> mItems;
private ListView mListView;


` public string acesstoken;`
` protected override void OnCreate(Bundle savedInstanceState)`

` {`
` base.OnCreate(savedInstanceState);`


SetContentView(Resource.Layout.Main);
mListView = FindViewById<ListView>(Resource.Id.myListView);

` mClient = new WebClient();`
` mUrl = new Uri("http://...link.../login");`
` mClient.DownloadDataAsync(mUrl);`


mClient.Headers.Add("User", ”email#gmail.com");
mClient.Headers.Add("Pass", ”myPassword”;
mClient.Headers.Add("Content-Type", "application/json");

mClient.Headers.Add("Accept", "application/json");


accesstoken = mClient.Headers.Get(”Accesstoken").ToString();


` mItems = new List<string>();`
` mItems.Add(accesstoken);`


 ArrayAdapter adapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleListItem1, mItems);

``

mListView.Adapter = adapter;


 }

}

`}
In Postman API tool
(I send username and password in headers and receive following text)
{
"Result": {
”mRegister": {
"allowed": 0,
”Testmsg": "**"
},
` …`
"token": ”EB9TEBINlVOASM0Ok04RlIjI8JGMVNVV1smFu5MT"
}
}
I know i have a lot to learn, but i would really appreciate your help so i can get started.
Thank you in advance!

Have you tried:
accesstoken = mClient.Headers.Get("token").ToString();
Getting token form json string.
Using Newtonsoft.Json library, create your response Json object. And get the token string.
Following example show how to create a User json object to get the username and password:
using Newtonsoft.Json;
public class MainActivity : Activity
{
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
BlobCache.ApplicationName = "AkavacheText";
string json = #"{ 'Username': 'Mike','Password': 'Ma'}";
SetContentView(Resource.Layout.Main);
var getData = JsonConvert.DeserializeObject<User>(json);
System.Console.WriteLine(getData.Username+"---"+ getData.Password);
}
}
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
string json should be your response string. User object should be your response object that structure depends on your json format.

Categories