Good day,
I need to build local notifications on my xamarin.forms, so i started from android:
1. In the core project i've created an interface:
public interface INotification
{
void CreateNotification();
}
2. In the Droid i've implemented notifications:
[assembly: Xamarin.Forms.Dependency(typeof(Notification))]
namespace Test.Droid
{
class Notification : Interfaces.INotification
{
public void CreateNotification()
{
string content = #"Here is the text";
int messageId = 999;
NotificationCompat.Builder builder = new NotificationCompat.Builder(Application.Context)
.SetAutoCancel(true)
.SetContentTitle("My Notifications")
.SetSmallIcon(Resource.Drawable.icon)
.SetContentText("Click here to next Activity")
.SetStyle(new NotificationCompat.BigTextStyle().BigText(content))
;
NotificationManager notificationManager = (NotificationManager)Application.Context.GetSystemService(Context.NotificationService);
notificationManager.Notify(messageId, builder.Build());
}
}
}
Finally, I put a dependency service on the main page of the core project
public MainPage()
{
InitializeComponent();
DependencyService.Get<INotification>().CreateNotification();
}
But i dont see a notification!
P.S. Its working fine on xamarin.android app.
The mistake was in a worng dependency :
[assembly: Xamarin.Forms.Dependency(typeof(Test.Droid.Notification))]
SOLVED
Related
I am using nuget package Xamarin.Firebase.Messaging and Xamarin.GooglePlayServices.Baseto receive push notifications in my app, previously it was working fine, but when I update visual studio 2022 to 17.2.3 it stopped working
I Tried all of these:
Update all nuget packages
delete obj bin folder from all shared projects
enable multidex
install and include
<PackageReference Include="Xamarin.Google.Guava" ExcludeAssets="all"> <Version>27.1.0</Version> </PackageReference>
https://techhelpnotes.com/c-working-through-package-reference-errors-with-firebase-and-a-java-exe-exited-with-code-1-error-xamarin/
https://github.com/xamarin/GooglePlayServicesComponents/issues/379
and nothing i did before has worked
my code to receive push notifications:
using System;
using System.Threading.Tasks;
using Android.App;
using Firebase.Messaging;
using Plugin.DeviceInfo;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace MyApp.Droid
{
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
readonly AndroidNotificationManager _androidNotification = new AndroidNotificationManager();
public override void OnMessageReceived(RemoteMessage message)
{
var mensajeData = message.Data;
string title= mensajeData["notiTitle"];
string bodymessage= mensajeData["notiBody"];
_androidNotification.CreateLocalNotification(title, bodymessage);
}
public override void OnNewToken(string token)
{
base.OnNewToken(token);
Preferences.Set("TokenFirebase", token);
}
}
}
if I remove [Service] or
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })] the code compiles correctly
Apparently it was due to the update I made of visual studio because the android SDK was also updated, the solution was to edit [Services] to [Services(Exported = true)] for android +31, leaving the final code like this.
[Service(Exported = true)]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
readonly AndroidNotificationManager _androidNotification = new AndroidNotificationManager();
public override void OnMessageReceived(RemoteMessage message)
{
var mensajeData = message.Data;
string title= mensajeData["notiTitle"];
string bodymessage= mensajeData["notiBody"];
_androidNotification.CreateLocalNotification(title, bodymessage);
}
public override void OnNewToken(string token)
{
base.OnNewToken(token);
Preferences.Set("TokenFirebase", token);
}
}
After adding that, everything compiled correctly
font answer
In addition to the answers here, I also had to export the broadcast reviver
[BroadcastReceiver(Enabled = true, Exported = true)]
I created a cross platform application using Xamarin. I need to call native functions of iOS and Android platform in my project. Here is the code:
private static Func<IDownloadFile, string> _downloadPath = new Func<IDownloadFile, string>(file =>
{
if (Device.RuntimePlatform == Device.iOS)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
else if (Device.RuntimePlatform == Device.Android)
{
string fileName = Android.Net.Uri.Parse(file.Url).Path.Split('/').Last();
return Path.Combine(Android.App.Application.Context.GetExternalFilesDir(Android.OS.Environment.DirectoryDownloads).AbsolutePath, fileName);
}
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "");
});
This is the code from notification plugin https://github.com/thudugala/Plugin.LocalNotification.
The problem is when I use that code the Mono.Android and Xamarin.iOS references are being added to my shared project in Dependencies/Assemblies and then when I try to run application in the release mode there is a reference error - I noticed that in my Android project in bin/Release there is Xamarin.iOS reference but there is no reference in Android project. When I remove that reference from Dependencies/Assemblies and comment native calls in my code everything compiles correctly. I am confused because of this. Is my above code correctly or I need to call native functions in another way?
When using .net Standard the approach taken is using an interface that defines the functionality you want to expose then implement in each platform.
In Shared:
public interface IMyInterface
{
string GetUrlPath(string fileUrl);
}
iOS Implementation:
public class MyClass : IMyInterface
{
public string GetUrlPath(string fileUrl)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
}
Android Implementation:
public class MyClass : IMyInterface
{
public string GetUrlPath(string fileUrl)
{
string fileName = (new NSUrl(file.Url, false)).LastPathComponent;
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);
}
}
Then using either Xamarin.Forms DependencyService or any other IoC container you can match the Interface with the correct implementation.
In your shared code you will use the Interface and the implementation picked will be transparent.
This post shows a very complete example of how to do it.
I'm working on a Xamarin Forms app and am trying to open the the default mail client directly to the Inbox.
I'm able to open and pass data through to compose a message using XF Essentials
Email.ComposeAsync(message);
But I would like the app to open the default mail app's Inbox on a button press. Is this possible in Xamarin Forms?
I think Dependency Service is what you need.
Create an interface in your Forms project:
public interface IOpenManager
{
void openMail();
}
Then implement it on each platform, for iOS:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.iOS
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
NSUrl mailUrl = new NSUrl("message://");
if (UIApplication.SharedApplication.CanOpenUrl(mailUrl))
{
UIApplication.SharedApplication.OpenUrl(mailUrl);
}
}
}
}
For Android:
[assembly: Dependency(typeof(OpenImplementation))]
namespace Demo.Droid
{
public class OpenImplementation : IOpenManager
{
public void openMail()
{
Intent intent = new Intent(Intent.ActionMain);
intent.AddCategory(Intent.CategoryAppEmail);
Android.App.Application.Context.StartActivity(intent);
}
}
}
At last, call this dependcy via: DependencyService.Get<IOpenManager>().openMail();
I'm develop cross-platform mobile application that use NFC. I already check the xamarin android beam here. Now i'm trying implement the same sample using xamarin forms so i'm using dependency service to call the function from android project. I try to make simple message that pass from device to another but it didn't work. The problem is the implementation of NfcAdapter.IOnNdefPushCompleteCallback
PhoneBeam.cs
using System;
using System.Text;
using Android.App;
using MyApp.Droid;
using Android.Nfc;
using Xamarin.Forms;
[assembly: Dependency(typeof(PhoneBeam))]
namespace MyApp.Droid
{
public class PhoneBeam : Activity, NfcAdapter.ICreateNdefMessageCallback, NfcAdapter.IOnNdefPushCompleteCallback, iBeam
{
private NfcAdapter nfcAdapter;
public void Beam()
{
nfcAdapter = NfcAdapter.GetDefaultAdapter(MainActivity.Instance);
nfcAdapter.SetNdefPushMessageCallback(this, MainActivity.Instance);
nfcAdapter.SetOnNdefPushCompleteCallback(this, MainActivity.Instance);
}
public NdefMessage CreateNdefMessage(NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" + "Beam : " +
time.ToString("HH:mm:ss"));
NdefMessage msg = new NdefMessage(
new NdefRecord[]{ CreateMimeRecord (
"application/com.example.android.beam",
Encoding.UTF8.GetBytes (text)) });
return msg;
}
public NdefRecord CreateMimeRecord(String mimeType, byte[] payload)
{
byte[] mimeBytes = Encoding.UTF8.GetBytes(mimeType);
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TnfMimeMedia, mimeBytes, new byte[0], payload);
return mimeRecord;
}
}
}
It says 'PhoneBeam does not implement interface member NfcAdapter.IOnNdefPushCompleteCallback.OnNdefPushComplete(NfcEvent)'. Am i missing something?
Your class implements IOnNdefPushCompleteCallback, which has a public method OnNdefPushComplete that must be implemented in order to satisfy the Interface.
I'm currently building a Xamarin.Forms project using MVVMCross. In order to test my platform specific code I am using Nunit.Xamarin which features an app that run tests on device.
This test app is a forms app but doesn't use MVVMCross and I haven't had any luck setting it up to use MVVMCross due to the fact the Application class loads an App of type NUnit.Runner.App whereas MVVMCross requires MvxFormsApp.
I want to test this class the saves and loads user data from an SQLite Database:
public class DataStorageService : IDataStorageService
{
private readonly SQLiteConnection _connection;
public User UserData
{
get { return _connection.Table<User>().FirstOrDefault(); }
set { _connection.InsertOrReplace(value); }
}
public DataStorageService(IMvxSqliteConnectionFactory factory)
{
_connection = factory.GetConnection(DataStorageConstants.LocalDatabaseName);
_connection.CreateTable<User>();
}
}
I want to actually test that it saves and loads from a local SQLite database so I don't want to mock the IMvxSqliteConnectionFactory. I tried installing MVVMCross and the SQLite plugin into the project and then passing in the Android implementation of the connection factory but that repeatedly threw a typeloadexception.
Any ideas as to how I can set up this test with MVVMCross (or are there alternatives?) and dependency injection?
It is possible :) The important stuff happens in the MvxSplashScreenActivity. The MvxFormsApp is basically empty. So we don't have to care. Example Code: https://github.com/smstuebe/stackoverflow-answers/tree/master/mvx-android-test-app
Create a nunit Test app project
Install-Package MvvmCross.StarterPack -Version 4.1.4
Get rid of Views folder
Install the SQLite plugin
Reference your Core project
Install-Package MvvmCross.Forms.Presenter -Version 4.1.4
Remove MainLauncher = true from MainActivity
Adust Setup to return your core project's App
protected override IMvxApplication CreateApp()
{
return new MyApp.Core.App();
}
Change SplashScreen to (source)
[Activity(MainLauncher = true
, Theme = "#style/Theme.Splash"
, NoHistory = true
, ScreenOrientation = ScreenOrientation.Portrait)]
public class SplashScreen
: MvxSplashScreenActivity
{
public SplashScreen()
: base(Resource.Layout.SplashScreen)
{
}
private bool _isInitializationComplete;
public override void InitializationComplete()
{
if (!_isInitializationComplete)
{
_isInitializationComplete = true;
StartActivity(typeof(MainActivity));
}
}
protected override void OnCreate(Android.OS.Bundle bundle)
{
Forms.Init(this, bundle);
Forms.ViewInitialized += (object sender, ViewInitializedEventArgs e) =>
{
if (!string.IsNullOrWhiteSpace(e.View.StyleId))
{
e.NativeView.ContentDescription = e.View.StyleId;
}
};
base.OnCreate(bundle);
}
}
Write a test like
[TestFixture]
public class TestClass
{
[Test]
public void TestMethod()
{
var service = Mvx.Resolve<IDataStorageService>();
Assert.IsNull(service.UserData);
}
}
Enjoy the awesomeness of MvvmCross