I have integrated FCM push notifications in xamarin android app. When foreground notifications delivering, notification click event calling MainActivity and from there it is not receiving and deleting all inserted records of SQLite because of that I am navigating to the wrong page. How can I retrieve my SQLite DB?
Thank you.
My Code:
click_action code:
[IntentFilter(new[] { "SISActivity" }, Categories = new[] { Intent.CategoryHome, Intent.CategoryDefault })]
public class SISActivity : AppCompatActivity
{
//from here need to navigation on other pages.
}
click_action sending with FCM notification
click_action":"SISActivity"
But code starting execution from MainActivity
Code in main activity for getting already logged in user
SQLiteAsyncConnection _conn;
_conn = DatabaseAccess.GetConnection();
//if table already created sqlite wont create it again
await _conn.CreateTableAsync<LoggedInUser>();
var objSisRepo = new SISRepository<LoggedInUser>(_conn);
var resultSingle = await objSisRepo.Get();
resultSingle getting 0 even if records available and deleting existing
records. Consequently, i am navigating to the login page instead of the Home page.
It is working fine when the app is in the background. I am using Async programming here.
SQLite connection getting method.
public static SQLiteAsyncConnection GetConnection()
{
SQLiteAsyncConnection con = null;
try
{
var sqlDbFileName = "edTheSIS.db3";
var documentsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var path = System.IO.Path.Combine(documentsPath, sqlDbFileName);
var connection = new SQLiteAsyncConnection(path);
con = connection;
return connection;
}
catch (Exception ex)
{
Toast.MakeText(Application.Context, "Something went wrong", ToastLength.Short).Show();
var objLog = new LogService();
objLog.MobileLog(ex, SISConst.UserName);
}
return con;
}
I don't know whether this is proper answer or not but near to it, and solved my problem. I was using AsyncSQLiteConnection , as I have posted my code. Now I have remove that and just using SQLiteConnection it is working for me. Thank you
Related
I am so frustrated with the Xamarin documentations. I am looking at doing one of the most basic thing, which is:
When a local notification comes out, a user taps the notification. It launches the App.
How do I handle this so that the app launches and acts according to the notification?
This is the official Xamarin Local Notifications documentation....
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/local-notifications
In Stack Overflow or google searches I can't find any Solutions.
Nothing is mentioned on how to act on a tap to the notification
Ah yes, the docs can be improved! They just assume that you understand it, you should add a pull request or an issue to improve that page!
After you have created:
The INotificationManager interface in the Core project,
The iOS platform changes- iOSNotificationManager, iOSNotificationReceiver, AppDelegate changes
The Android platform changes- AndroidNotificationManager, MainActivity changes, if needed BroadcastReceiver
Then in the constructor of the page where you want to handle the changes, get the instance of the NotificationManager, and then subscribe to the NotificationReceived event which should get called when a user taps on the notification item.
public DashboardPage()
{
InitializeComponent();
notificationManager = DependencyService.Get<INotificationManager>();
notificationManager.NotificationReceived += (sender, eventArgs) =>
{
var evtData = (NotificationEventArgs)eventArgs;
Console.WriteLine("Title & Message: " + evtData.Title + evtData.Message);
};
}
You could try Plugin.LocalNotification too, it has a feature can hanle tap event, like:
public partial class App : Application
{
public App()
{
InitializeComponent();
// Local Notification tap event listener
NotificationCenter.Current.NotificationTapped += OnLocalNotificationTapped;
MainPage = new MainPage();
}
private void OnLocalNotificationTapped(NotificationEventArgs e)
{
// your code goes here
}
}
edit:
On iOS:
You can add code in DidRecieveNotiticationResponse(),like:
public override void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler)
{
if (response.IsDefaultAction)
{
ProcessNotification(response.Notification);
}
Console.WriteLine("Called");
App.Current.MainPage=new Page();
completionHandler();
}
I'm using pusher in my app to get some live values in-app from the server.
I'm subscribing to static channelName but somehow the user can't get data from the server if he keeps the app for a long time open, if the user restarts the app it works fine.
in the pusher dashboard it works well and shows data go to users but, it's not.
when I read on pusher I found that there is ping-pong but, even if I increased pong time it fails too
here is my code:
1- for pusher & channel create ( called in on create ):
options = new PusherOptions();
String APP_CLUSTER = "APP_CLUSTER ";
options.setCluster(APP_CLUSTER);
String APP_KEY = "APP_KEY ";
pusher = new Pusher(APP_KEY, options);
pusher.connect(new ConnectionEventListener() {
#Override
public void onConnectionStateChange(ConnectionStateChange change) {
Log.e("PUSHER SUCCESS => ", change.getCurrentState().name());
}
#Override
public void onError(String message, String code, Exception e) {
Log.e("PUSHER FAILED => ", message);
}
}, ConnectionState.ALL);
2- channel bind & subscribe ( called in onResume ):
channel = pusher.subscribe("xxx");
channel.bind("MessageCreated", event -> {
Log.e("PUSHER DATA => ", event.getData());
});
3- channel un-subscribe ( called in onPause):
pusher.unsubscribe("xxx");
4- disconnect pusher ( called in onDestroy ):
pusher.disconnect();
I hope if anyone can give me the reason for disconnecting for some users, can someone tell me
I have an application that in server side we configured a socket.IO for it.
and I want to connect my application to that, listening to server when an event happened ,then my application Log a message in android side.
I have a BaseActivity that all of my activities extends from that. and in BaseActivity I setup Socket.IO:
protected var mSocket: Socket? = null
try {
mSocket = IO.socket("http://myDomain.co")
} catch (e: URISyntaxException) {
}
mSocket!!.connect()
then in target activity I use this code:
mSocket!!.on("record_create", { args ->
this#MainPage.runOnUiThread({
val data = args[0] as JSONObject
Log.i("LOGGG", data.getString("record_create").toString())
})
})
but nothings happened!
whats my problem?
Or
How can I do this job in best way?
I solved this problem by myself:
by initializing socket.io in target activity, and call socket.io listeners in this class
I am attempting to create a real-time communication capability for a Phonegap/Cordova app. I am using SignalR 2 to handle the communication.
The thing I am struggling with is getting a message to a particular user. Every single example out there shows saving Context.User.Identity.Name, which is useless to me because the remote site's User.Identity context is not shared by my phonegap app.
In essence, I am not authenticating a user in the traditional sense, so I need another way of linking the SignalR connectionID with the username I pass along.
Taken from the official ASP.NET signalr Examples, I have the following code which overrides the OnConnected event. Unfortunately it takes no parameters and expects User.Identity to be not null:
public override Task OnConnected()
{
using (var db = new UserContext())
{
// Retrieve user.
var user = db.Users
.Include(u => u.Rooms)
.SingleOrDefault(u => u.UserName == Context.User.Identity.Name);
// If user does not exist in database, must add.
if (user == null)
{
user = new User()
{
UserName = Context.User.Identity.Name
};
db.Users.Add(user);
db.SaveChanges();
}
else
{
// Add to each assigned group.
foreach (var item in user.Rooms)
{
Groups.Add(Context.ConnectionId, item.RoomName);
}
}
}
return base.OnConnected();
}
Now, maybe what I'd need is to have a version of this method that takes a string as a parameter and then I'd use that as my user identifier.
But how to go about that?
You need to create a new IUserIdProvider for the user and use dependency injection to register your provider and use it.
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
Register your provider with Global Host
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new MyIdProvider());
Usage:
public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}
Taken from: http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections#IUserIdProvider
First off I am using Xamarin Forms for a WP8, iOS and Android app.
Goal:
I want to go to a specific page when the toast is clicked depending
upon the payload information of the toast notification.
I have push notifications using Azure Notification Hubs all setup and working well. I use MVVMLight and their dependency injection to setup push notifications specifically for each platform.
Each payload needs to be sent a little different due to the different formats required. With each you will notice I want to send a SignalId in the payload to perform a different action as required on the receiving device from regular push notifications.
Android
{
"data" : {
"msg" : "message in here",
"signalId" : "id-in-here",
},
}
iOS
{
"aps" : { "alert" : "message in here" },
"signalId" : "id-in-here"
}
Windows Phone 8
<?xml version="1.0" encoding="utf-8"?>
<wp:Notification xmlns:wp="WPNotification">
<wp:Toast>
<wp:Text1>category</wp:Text1>
<wp:Text2>message in here</wp:Text2>
<wp:Param>?signalId=id-in-here</wp:Param>
</wp:Toast>
</wp:Notification>
.
Question:
How do I get this information in a Xamarin Forms app and redirect to
the appropriate page when the application is reactivated because the
user clicked on the toast notification?
I want to get the payload information when the app loads, then say, yes this contains a SignalId, lets redirect to this page.
At the moment all it does it show the application when a toast notification is clicked. Must I do it specific to the app, or is there a Xamarin Forms way?
Any help appreciated even if you only know how to do it for one platform, I can probably work my way around the other platforms from there.
I have found the way to do it for all platforms. Windows has been tested, Android and iOS haven't.
Windows and iOS work on a show toast notification if the app is in the background, or let your code deal with it if the app is in the foreground. Android shows the toast regardless of application status.
With Windows Phone 8 I need to go to the MainPage.xaml.cs and add in this override.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (this.NavigationContext.QueryString.ContainsKey("signalId"))
{
var signalId = this.NavigationContext.QueryString["signalId"];
var id = Guid.Empty;
if (signalId != null
&& Guid.TryParse(signalId, out id)
&& id != Guid.Empty)
{
this.NavigationContext.QueryString.Clear();
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// Do my navigation to a new page
});
}
}
}
For Android in the GcmService
protected override void OnMessage(Context context, Intent intent)
{
Log.Info(Tag, "GCM Message Received!");
var message = intent.Extras.Get("msg").ToString();
var signalId = Guid.Empty;
if (intent.Extras.ContainsKey("signalId"))
{
signalId = new Guid(intent.Extras.Get("signalId").ToString());
}
// Show notification as usual
CreateNotification("", message, signalId);
}
Then in the CreateNotification function put some extra information in the Intent.
var uiIntent = new Intent(this, typeof(MainActivity));
if (signalId != Guid.Empty)
{
uiIntent.PutExtra("SignalId", signalId.ToString());
}
Then in the MainActivity.cs override this function
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
if (data.HasExtra("SignalId"))
{
Guid signalId = new Guid(data.GetStringExtra("SignalId"));
if (signalId != Guid.Empty)
{
data.RemoveExtra("SignalId");
// Do you navigation
}
}
}
In iOS you will notice I have enhanced the default ProcessNotification()
void ProcessNotification(NSDictionary options, bool fromFinishedLaunching)
{
// Check to see if the dictionary has the aps key. This is the notification payload you would have sent
if (null != options && options.ContainsKey(new NSString("aps")))
{
//Get the aps dictionary
var aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
var alert = string.Empty;
//Extract the alert text
// NOTE: If you're using the simple alert by just specifying
// " aps:{alert:"alert msg here"} " this will work fine.
// But if you're using a complex alert with Localization keys, etc.,
// your "alert" object from the aps dictionary will be another NSDictionary.
// Basically the json gets dumped right into a NSDictionary,
// so keep that in mind.
if (aps.ContainsKey(new NSString("alert")))
alert = ((NSString) aps[new NSString("alert")]).ToString();
// If this came from the ReceivedRemoteNotification while the app was running,
// we of course need to manually process things like the sound, badge, and alert.
if (!fromFinishedLaunching)
{
//Manually show an alert
if (!string.IsNullOrEmpty(alert))
{
var signalId = new Guid(options.ObjectForKey(new NSString("signalId")) as NSString);
// Show my own toast with the signalId
}
}
}
}
Then in the FinishedLaunching function check if there is any payload
// Check if any payload from the push notification
if (options.ContainsKey("signalId"))
{
var signalId = new Guid(options.ObjectForKey(new NSString("signalId")) as NSString);
// Do the navigation here
}