Why Can't I register my android device? xam.pushnotification - xamarin

I am using xam.plugin.pushnotification in my xamarin.forms project
my main activity
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
//inicializa imageCircle
ImageCircleRenderer.Init();
//inicializa o mapa
global::Xamarin.FormsMaps.Init(this, bundle);
//shared Preferences
App.Init(new AndroidUserPreferences());
//Gerenciador de memória
CachedImageRenderer.Init();
try
{
AppContext = this.ApplicationContext;
CrossPushNotification.Initialize<CrossPushNotificationListener>("my sender");
StartPushService();
}
catch (Exception e)
{
var s = e.Message;
}
AndroidUserPreferences sharedPref = new AndroidUserPreferences();
if ( sharedPref.GetString("token") == " ")
{
GetTokenTask myTask = new GetTokenTask();
myTask.Execute(this);
}
LoadApplication(new App());
}
public static void StartPushService()
{
AppContext.StartService(new Intent(AppContext, typeof(PushNotificationService)));
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
{
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0);
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
alarm.Cancel(pintent);
}
}
public static void StopPushService()
{
AppContext.StopService(new Intent(AppContext, typeof(PushNotificationService)));
if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.Kitkat)
{
PendingIntent pintent = PendingIntent.GetService(AppContext, 0, new Intent(AppContext, typeof(PushNotificationService)), 0);
AlarmManager alarm = (AlarmManager)AppContext.GetSystemService(Context.AlarmService);
alarm.Cancel(pintent);
}
}
My listener in my pcl
public class CrossPushNotificationListener : IPushNotificationListener
{
public void OnMessage(JObject values, DeviceType deviceType)
{
Debug.WriteLine("Message Arrived");
}
public void OnRegistered(string token, DeviceType deviceType)
{
Debug.WriteLine(string.Format("Push Notification - Device Registered - Token : {0}", token));
}
public void OnUnregistered(DeviceType deviceType)
{
Debug.WriteLine("Push Notification - Device Unnregistered");
}
public void OnError(string message, DeviceType deviceType)
{
Debug.WriteLine(string.Format("Push notification error - {0}",message));
}
public bool ShouldShowNotification()
{
return true;
}
}
}
Registering (trying LOL) in app.cs (PCL)
public App()
{
InitializeComponent();
CrossPushNotification.Current.Register();
MainPage = new NavigationPage(new Views.Splash2());
}
I registered my project in firebase using the package name, then I created a project there and getted the sender ID...BUT...
after call "cross...current.register()", somewhere (it doesn't show me where), I have a exception
FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not resolve type with token 0100005a (from typeref, class/assembly Android.Gms.Gcm.Iid.InstanceID, Xamarin.GooglePlayServices.Gcm, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null)
do i need to install xamarin.gcm in my pcl project? now it is only in my android project

Try calling CrossPushNotification.Current.Register (); into OnCreate method. Like this:
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
//inicializa imageCircle
ImageCircleRenderer.Init();
//inicializa o mapa
global::Xamarin.FormsMaps.Init(this, bundle);
//shared Preferences
App.Init(new AndroidUserPreferences());
//Gerenciador de memória
CachedImageRenderer.Init();
try
{
AppContext = this.ApplicationContext;
CrossPushNotification.Initialize<CrossPushNotificationListener>("my sender");
//call register method here
CrossPushNotification.Current.Register();
StartPushService();
}
catch (Exception e)
{
var s = e.Message;
}
AndroidUserPreferences sharedPref = new AndroidUserPreferences();
if ( sharedPref.GetString("token") == " ")
{
GetTokenTask myTask = new GetTokenTask();
myTask.Execute(this);
}
LoadApplication(new App());
}

I had to migrate to 1.2.5-beta too, it does work, BUT the plugin was recently announced as DEPRECATED.
Thats bad news.
In order to support monoandroid80 I had to fork xam.plugin.pushnotification and update its packages.config manually.
There soon would be no other choice but to migrate.

Related

Xamarin - download image to gallery

I've found this: How to download image and save it in local storage using Xamarin-Forms.?
This partially adresses my problem except for two points:
I'd need to download the image to the gallery, not the apps'path
I need this to work for both, android and IOs. This seems to only work for Android.
Basically i know the URL of a file online, and need to download it to the gallery. It would be great if ic ould "save" it from inside the application, instead of "downloading". It would be nice if the client cant figure out the URL of the images he wants to save.
EDIT:
Now I am using FFImageLoading.. here is my current (not working) code..
private async void SaveToGallery_Clicked(object sender, EventArgs e)
{
var img = await MyImage.GetImageAsJpgAsync(quality: 100);
string fileName = uri.ToString().Split('/').Last();
DependencyService.Get<IMediaService>().SaveImageFromByte(img, fileName);
}
Android MediaService.cs
[assembly: Xamarin.Forms.Dependency(typeof(MediaService))]
namespace GalShare.Droid
{
public class MediaService : IMediaService
{
Context CurrentContext => CrossCurrentActivity.Current.Activity;
public void SaveImageFromByte(byte[] imageByte, string fileName)
{
try
{
Java.IO.File storagePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures);
string path = System.IO.Path.Combine(storagePath.ToString(), fileName);
System.IO.File.WriteAllBytes(path, imageByte);
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(path)));
CurrentContext.SendBroadcast(mediaScanIntent);
}
catch (Exception ex)
{
}
}
}
}
Android MainActivity.cs:
namespace GalShare.Droid
{
[Activity(Label = "GalShare", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public int STORAGE_PERMISSION_CODE = 101;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
FFImageLoading.Forms.Platform.CachedImageRenderer.Init(enableFastRenderer: false);
base.OnCreate(savedInstanceState);
Forms.SetFlags("CollectionView_Experimental");
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
CachedImageRenderer.InitImageViewHandler();
string fileName = "galleries.db3";
string folderPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string completePath = Path.Combine(folderPath, fileName);
checkPermission("android.permission.write_external_storage", STORAGE_PERMISSION_CODE);
LoadApplication(new App(completePath));
}
public void checkPermission(String permission, int requestCode)
{
var thisActivity = Android.App.Application.Context as Activity;
// Checking if permission is not granted
if (ContextCompat.CheckSelfPermission(
Android.App.Application.Context,
permission)
== Android.Content.PM.Permission.Denied)
{
RequestPermissions(new String[] { Manifest.Permission.WriteExternalStorage }, requestCode);
}
else
{
}
}
}
}
Initialilzing CrossCurrentActivity in the MainActivity.cs solved the problem:
CrossCurrentActivity.Current.Init(this, bundle);

How can we change the ringer mode in xamarin form

Runtime error when I try to change ringer mode to normal.i am using dependency service to call audio manager in android in xamarin form but code runs without error when the ringer mode change to silent ( maybe it's already silent)
About changing ringer mode, you can follow these steps.
1.define a interface in Xamarin.Forms PCL.
public interface IChangeRingModeService
{
void changeRingModeToNormal();
void changeRingModeToVibrate();
void changeRingModeToSilent();
}
In Android project, implement this interface in Mainactivity.cs, please don't forget register dependency
[assembly: Dependency(typeof(MainActivity))]
namespace App4.Droid
{
[Activity(Label = "App4", Icon = "#mipmap/icon", Theme = "#style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize| ConfigChanges.Orientation)]
public class MainActivity :
global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IChangeRingModeService
{
AudioManager am;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
public void changeRingModeToVibrate()
{
am = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
am.RingerMode = RingerMode.Vibrate;
}
public void changeRingModeToNormal()
{
am = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
am.RingerMode = RingerMode.Normal;
}
public void changeRingModeToSilent()
{
am = (AudioManager)Android.App.Application.Context.GetSystemService(Context.AudioService);
am.RingerMode = RingerMode.Silent;
}}}
call this method in click event.
private void Button1licked(object sender, EventArgs e)
{
DependencyService.Get<IChangeRingModeService>().changeRingModeToVibrate();
}
private void Button2licked(object sender, EventArgs e)
{
DependencyService.Get<IChangeRingModeService>().changeRingModeToNormal();
}
private void Button3licked(object sender, EventArgs e)
{
DependencyService.Get<IChangeRingModeService>().changeRingModeToSilent();
}

Xamarin android - Attempt to invoke virtual method sendBroadcast() on a null object reference

I'm building a crossplatform application using Xamarin,my application will download videos from internet, I've done the download and save functions, but after saved videos to DCIM(in android) the videos do not appear in gallery.After hafl of a day searching for solutions on internet I comeup with two solutions:
1.after download finished: send broadcast with action "Intent.ActionMediaMounted".
2.after download finished Call "MediaScannerConnection.ScanFile".
With solution 1 I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'void android.content.Context.sendBroadcast(android.content.Intent)' on a null object reference}
With solution 2, I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Context.bindService(android.content.Intent, android.content.ServiceConnection, int)' on a null object reference}
This is my Interface which I used to handle downloadfinished placed in PLC project:
namespace VideoDownloader
{
public interface IDownloadState
{
void OnDownloadStarted();
void OnDownloadError();
void OnDownloadFinished(string path);
}
}
This is my MainPage.xaml.cs in PLC project:
namespace VideoDownloader
{
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
public void downloadVideo(VideoInfor video, bool isRetried)
{
//download code here...
DependencyService.Get<IDownloadState()
.OnDownloadFinished(video.path);
}
}
}
And This is my MainActivity in Android project which implement IDownloadState and send broadcast when OnDownloadFinished fired:
[assembly: Xamarin.Forms.Dependency(typeof(MainActivity))]
namespace VideoDownloader.Droid
{
[Activity(Label = "VideoDownloader", Icon = "#mipmap/icon", Theme =
"#style/MainTheme", MainLauncher = true, ConfigurationChanges =
ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity :
global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,
IDownloadState
{
readonly string[] StoragePermissions =
{
Manifest.Permission.WriteExternalStorage,
Manifest.Permission.ReadExternalStorage
};
const int RequestStorageId = 0;
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
int sdkBuildVersion = (int)Build.VERSION.SdkInt;
Console.WriteLine("SDK build version = " + sdkBuildVersion);
if (sdkBuildVersion >= 23)
{
RequestStoragePermission();
}
}
public override void OnRequestPermissionsResult(int requestCode,
string[] permissions, Permission[] grantResults)
{
switch (requestCode)
{
case RequestStorageId:
{
if (grantResults[0] == Permission.Granted)
{
}
else
{
}
}
break;
default:
break;
}
}
public void OnDownloadStarted()
{
throw new NotImplementedException();
}
public void OnDownloadError()
{
throw new NotImplementedException();
}
public void OnDownloadFinished(string path)
{
//Intent intent = new Intent(Intent.ActionMediaMounted);
//SendBroadcast(intent);
//throw new NotImplementedException();
MediaScannerConnection.ScanFile(this, new String[] {
Android.OS.Environment
.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim)
.AbsolutePath }, null, null);
}
}
}
I know there are many many similar questions for android on stackoverflow that have ansered but they seem to not like my situation at all. So is there anyone know what am I doing wrong? Why this is happening?
With solution 2, I got:
"{Java.Lang.NullPointerException: Attempt to invoke virtual method 'boolean android.content.Context.bindService(android.content.Intent, android.content.ServiceConnection, int)' on a null object reference}
Please try to use Forms.Context instead of this in OnDownloadFinished().
For example:
public void OnDownloadFinished(string path)
{
//Intent intent = new Intent(Intent.ActionMediaMounted);
//SendBroadcast(intent);
//throw new NotImplementedException();
MediaScannerConnection.ScanFile(Forms.Context, new String[] {
Android.OS.Environment
.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim)
.AbsolutePath }, null, null);
}

How to use wikitude plugin in xamarin forms?

I am using Xamarin to develop cross platform AR application. I am using Wikitude instant tracking.
I am able to start the Wikitude activity and able to run the Instant tracking...Now I want capture the high resolution image while tracking...I am trying to build the plugin to get the frame and then convert it to image stream
Her is my Wikitude activity
namespace XamarinExample.Droid
{
[Activity(Label = "WikitudeActivity")]
public class WikitudeActivity : Activity, ArchitectView.IArchitectUrlListener
{
ArchitectView architectView;
string worldUrl;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.sample_cam);
Title = Intent.GetStringExtra("id");
worldUrl = "Wikitude" + File.Separator + Intent.GetStringExtra("id") + File.Separator + "index.html";
architectView = FindViewById<ArchitectView>(Resource.Id.architectView);
ArchitectStartupConfiguration startupConfiguration = new ArchitectStartupConfiguration();
startupConfiguration.setLicenseKey(Constants.WIKITUDE_SDK_KEY);
startupConfiguration.setFeatures(ArchitectStartupConfiguration.Features.ImageTracking);
startupConfiguration.setCameraResolution(CameraSettings.CameraResolution.Auto);
/////////////////////////////// Register Plugin////////////////////////////////////
var plugins = new Plugin01("test");
architectView.RegisterPlugin(plugins);
architectView.OnCreate(startupConfiguration);
architectView.RegisterUrlListener(this);
}
}
My Plugin code taken from
public class Plugin01 : Com.Wikitude.Common.Plugins.Plugin
{
public Plugin01(string p0) : base(p0)
{
}
Frame currentFrame = null;
public override void CameraFrameAvailable(Frame p0)
{
System.Diagnostics.Debug.WriteLine("AVAILABLE FRAME");
try
{
var data = p0.GetData();
currentFrame = p0;
}
catch (System.Exception ex) { }
}
public override void Update(RecognizedTarget[] p0)
{
System.Diagnostics.Debug.WriteLine("AVAILABLE FRAME");
if (p0 != null)
{
if (currentFrame != null)
{
// ConvertYuvToJpeg(currentFrame, p0[0]);
}
}
}
}
I have registered the plugins but it is not calling
public override void Update(RecognizedTarget[] p0) Method....What am I doing wrong here ?
I think the problem is calling "RegisterPlugin" in the wrong method, as you know the cycle of calling activity methods are different.you should call it in "OnPostCreate" method of activity.
try below code and let me know the result:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
try
{
SetContentView(Resource.Layout.Main);
architectView = FindViewById<ArchitectView>(Resource.Id.architectView);
var config = new ArchitectStartupConfiguration();
config.setLicenseKey(WIKITUDE_SDK_KEY);
architectView.OnCreate(config);
}
catch (Exception ex) { Toast.MakeText(this, ex.ToString(), ToastLength.Long); }
}
protected override void OnPostCreate(Bundle savedInstanceState)
{
base.OnPostCreate(savedInstanceState);
if (architectView != null)
architectView.OnPostCreate();
try
{
try
{
string url = string.Format(#"file:///android_asset/01_ImageRecognition_1_ImageOnTarget/index.html");
architectView.Load(url);
Plugin01 cardPlugin = new Plugin01("com.plugin.dpiar");
architectView.RegisterPlugin(cardPlugin);
}
catch (Exception ex) { }
}
catch (Exception ex) { Toast.MakeText(this, ex.ToString(), ToastLength.Long); }
}
consider changing variables name.

DisplayAlert With changing Text xamarin forms

I have a requirement where i have to show the status of the download on a DisplayAlert. But with changing text on it asynchronously.
How to achieve this?
DisplayAlert("Download Info", "Downloading.....", "Ok");
I want to show status like...
Connected to server
Downloading
Download Complete
Here is a simple "Dynamic Alert" for Forms and iOS using UIAlertController and Android using a DialogFragment and a Xamarin.Forms dependency service:
Dependency Interface:
public interface IDynamicAlert
{
void Show(string title, string message);
void Update(string message);
void Dismiss();
}
iOS IDynamicAlert Dependency Implementation:
public class DynamicAlert : IDynamicAlert
{
UIAlertController alert;
public void Show(string title, string message)
{
if (alert != null) throw new Exception("DynamicAlert already showing");
alert = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);
var rootVC = UIApplication.SharedApplication.Windows[0].RootViewController;
rootVC.PresentViewController(alert, true, () =>
{
});
}
public void Update(string message)
{
if (alert == null) throw new Exception("DynamicAlert is not showing, call Show first");
alert.Message = message;
}
public void Dismiss()
{
if (alert == null) throw new Exception("DynamicAlert is not showing, call Show first");
alert.DismissViewController(true, () =>
{
alert.Dispose();
alert = null;
});
}
}
Example Usage:
var alert = DependencyService.Get<IDynamicAlert>();
if (alert != null)
{
alert.Show("StackOverflow", "Starting your request...");
await Task.Delay(2000); // Do some work...
alert.Update("Your request is processing...");
await Task.Delay(2000); // Do some work...
alert.Update("Your request is complete...");
await Task.Delay(750);
alert.Dismiss();
}
else
{
throw new Exception("IDynamicAlert Dependency not found");
}
Output:
Android Version:
The android version consists of a couple of parts, a DialogFragment subclass and the IDynamicAlert implementation that uses the custom DialogFragment.
Android DialogFragment Subclass:
public class DynamicAlertDialogFragment : DialogFragment
{
AlertDialog alertDialog;
readonly Context context;
public static DynamicAlertDialogFragment Instance(Context context, string title, string message)
{
var fragment = new DynamicAlertDialogFragment(context);
Bundle bundle = new Bundle();
bundle.PutString("title", title);
bundle.PutString("message", message);
fragment.Arguments = bundle;
return fragment;
}
public DynamicAlertDialogFragment(Context context)
{
this.context = context;
}
public override Dialog OnCreateDialog(Bundle savedInstanceState)
{
var title = Arguments.GetString("title");
var message = Arguments.GetString("message");
alertDialog = new AlertDialog.Builder(context)
.SetIcon(Android.Resource.Drawable.IcDialogInfo)
.SetTitle(title)
.SetMessage(message)
.Create();
return alertDialog;
}
public void SetMessage(string message)
{
(context as Activity).RunOnUiThread(() => { alertDialog.SetMessage(message);});
}
}
Android IDynamicAlert Dependency Implementation:
public class DynamicAlert : IDynamicAlert
{
const string FRAGMENT_TAG = "DynamicAlert_Fragment";
DynamicAlertDialogFragment fragment;
static FormsAppCompatActivity currentActivity;
public static FormsAppCompatActivity CurrentActivity { set { currentActivity = value; } }
public void Show(string title, string message)
{
if (currentActivity == null) throw new Exception("DynamicAlert.CurrentActivity needs assigned");
var fragMgr = currentActivity.FragmentManager;
var fragTransaction = fragMgr.BeginTransaction();
var previous = fragMgr.FindFragmentByTag(FRAGMENT_TAG);
if (previous != null)
{
fragTransaction.Remove(previous);
}
fragTransaction.DisallowAddToBackStack();
fragment = DynamicAlertDialogFragment.Instance(currentActivity, title, message);
fragment.Show(fragMgr, FRAGMENT_TAG);
}
public void Update(string message)
{
if (fragment == null) throw new Exception("DynamicAlert is not showing, call Show first");
fragment.SetMessage(message);
}
public void Dismiss()
{
if (fragment == null) throw new Exception("DynamicAlert is not showing, call Show first");
fragment.Dismiss();
fragment.Dispose();
fragment = null;
}
}
Android Init / Usage:
When creating the AlertDialog in the DialogFragment we need access to the current Activity and when using Xamarin.Forms, that is normally the MainActivity that is a FormsAppCompatActivity subclass. Thus you will need to initialize the DynamicAlert.CurrentActivity static property with this Activity in your MainActivity.OnCreate subclass:
Example:
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
////////////
DynamicAlert.CurrentActivity = this;
////////////
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App());
}
Android Output:

Resources