I'm a beginner to android app development. I waned to access incoming notifications from my flutter app. I tried https://pub.dev/packages/notifications package. But I can't find how it works.
I also tried to use the NotificationListener but can't figure it out.
Please help if you can.
The notifications package listens to notifications/push messages received by the device. The messages received should be handled inside onData.
Notifications _notifications;
StreamSubscription<NotificationEvent> _subscription;
...
void onData(NotificationEvent event) {
debugPrint('Event received: $event');
}
void startListening() {
_notifications = new Notifications();
try {
_subscription = _notifications!.notificationStream!.listen(onData);
} on NotificationException catch (exception) {
debugPrint(exception);
}
}
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 want to set up a mobile application with flutter which also runs in the background. this application allows you to scan Bluetooth devices and listen to events to launch notification and/or start a ringtone.
I managed to do all this and it works very well with the flutter_blue plugin. But my problem is that the application has to keep running in the background.
I came here to seek help.
The app does exactly what this app does https://play.google.com/store/apps/details?id=com.antilost.app3&hl=fr&gl=US
There are 2 ways to do it.
All you have to do that is write a native code in JAVA/Kotlin for android and obc-c/swift for ios.
The best place to start with this is here
If you just follow the above link then you will be able to code MethodChannel and EventChannel, which will be useful to communicate between flutter and native code. So, If you are good at the native side then it won't be big deal for you.
// For example, if you want to start service in android
// we write
//rest of the activity code
onCreate(){
startBluetoothService();
}
startBluetoothService(){
//your code
}
//then, For the flutter
// Flutter side
MessageChannel msgChannel=MessageChannel("MyChannel");
msgChannel.invokeMethode("startBluetoothService");
// Native side
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "MyChannel";
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("startBluetoothService")) {
int response = startBluetoothService();
//then you can return the result based on the your code execution
if (response != -1) {
result.success(response);
} else {
result.error("UNAVAILABLE", "Error while starting service.", null);
}
} else {
result.notImplemented();
}
}
);
}
}
same as above you can write the code for the iOS side.
Second way is to write your own plugin for that you can take inspiration from alarm_manager or Background_location plugins.
I hope it helps you to solve the problem.
Sinch In-App Instant Messaging works perfectly fine with Sinch Managed Push but except this one issue.
This is the sistuation - I receives messages using GCM Listener when my app is foreground or background and I show notification but except in the case when my app is not running.
I inserted debug logs statements to see the flow and it seems that push message arrives in the GCM Listener and gets sent to my service as well but it never gets relayed to the message client listener. This only happens when the app is not running or is closed.
I am doing the following when the app is running background or foreground and I do get callback in onIncomingMessage but same code doesn't work when app is not running.
Sinch Client Initialization Code:
public void startSinchClient(String username) {
try {
sinchClient = Sinch.getSinchClientBuilder().context(this).userId(username).applicationKey(ApplicationConstants.SINCH_SANDBOX_API_KEY)
.applicationSecret(ApplicationConstants.SINCH_SANDBOX_API_SECRET).environmentHost(ApplicationConstants.SINCH_SANDBOX_API_URL).build();
sinchClient.setSupportMessaging(true);
sinchClient.setSupportManagedPush(true);
sinchClient.checkManifest();
sinchClient.addSinchClientListener(this);
if ( messageClientListener == null ) {
messageClientListener = new MyMessageClientListener();
}
sinchClient.getMessageClient().addMessageClientListener(messageClientListener);
Log.e("SinchMessageService", "Login successful.");
} catch (MissingGCMException missingGCM) {
Log.e("SinchMessageService", missingGCM.getMessage());
}
}
OnBind Code
if (!isSinchClientStarted()) {
startSinchClient(currentUserId);
sinchClient.start();
}
In RelayRemotePushNotificationCode:
public NotificationResult relayRemotePushNotificationPayload(Intent intent) {
if ( currentUserId.isEmpty() ) {
Log.e("SinchMessageService", "UserID not available.Please login again.");
return null;
} else if ( !isSinchClientStarted() ) {
startSinchClient(currentUserId);
sinchClient.start();
}
Log.d("SinchService", "relayRemotePushNotificationPayload");
NotificationResult notificationResult = sinchClient.relayRemotePushNotificationPayload(intent);
if (notificationResult.isMessage()) {
sinchClient.startListeningOnActiveConnection();
}
return notificationResult;
}
In MessageClientListener:
public void onIncomingMessage(MessageClient client, final Message message) {
if (message.getRecipientIds().get(0).equals(ApplicationConstants.userInfo.getEmail())) {
sinchClient.stopListeningOnActiveConnection();
....
The above code works in all the scenarios. I mean when the app is running in foreground as well as background. Only when I kill the app never get the onIncomingMessage callback.
Log statements from Sinch Client:
03-03 22:07:44.213 17381-17381/com.ontyme E/SinchClient: mUserAgent.startBroadcastListener()
03-03 22:07:45.271 17381-17381/com.ontyme E/MessageClient: onIncomingMessage: NativeMessage [id=2059913a-27ac-4105-a797-764f09af66d2, nativeAddress=-1321533856]
Anyone else has faced the issue?
Sorry guys there is no problem with the Sinch Managed Push. It was small typo at my end which was causing this issue. My receipentid in the app was not getting initialized correctly when the app was not running which is why all the messages were getting ignored in onIncomingMessage.
Managed Push works seamlessly for me now.
I'm trying to send String from my Moto 360 to Android App! but I don't understand how to implement the code in documentation, can anyone help me please with a little explanation of the steps to follow to send data !
http://developer.android.com/training/wearables/data-layer/messages.html
Take a look at a samples, this line exactly shows how to send a message:
http://developer.android.com/samples/DataLayer/Application/src/com.example.android.wearable.datalayer/MainActivity.html#l335
private void sendStartActivityMessage(String node) {
Wearable.MessageApi.sendMessage(
mGoogleApiClient, node, START_ACTIVITY_PATH, new byte[0]).setResultCallback(
new ResultCallback<SendMessageResult>() {
#Override
public void onResult(SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e(TAG, "Failed to send message with status code: "
+ sendMessageResult.getStatus().getStatusCode());
}
}
}
);
}
If that's too much information, a simpler tutorial for MessageApi should be just a google search away. Try this one: http://www.binpress.com/tutorial/a-guide-to-the-android-wear-message-api/152 it looks reasonable.
I have to Users (User A and B) and one Chromecast device (C1).
User B starts a stream on C1.
User A connects to C1
Now User A should be able to control the stream running on C1. But every time I want to start a session the running stream on C1 is shut down and the receiver app is restarting.
Is there a way to join an active session? Or is that a job which has to be done by the web app running on the Chromecast device?
EDIT:
my sender app is a native Android app
Thanks!
You should have a look to the TicTacToe application. I think it does exactly that where 2 players can join the same game :
https://github.com/googlecast/cast-android-tictactoe
Hope this helps.
JN
What sort of sender are you using? Is it a native app (i.e. using Android or iOs SDK on a mobile device) or the sender is a chrome app?
On the receiver, you create a Receiver object and a ChannelHandler. You use the receiver to generate a ChannelFactory which you then pass to the ChannelHandler. The ChannelHandler now handles the creation of channels on the receiver. You will want to add an EventListener to the handler to listen to messages. Based on those messages you can do various things.
receiver = new cast.receiver.Receiver(YOUR_APP_ID, [YOUR_PROTOCOL], "", 5);
var dashHandler = new cast.receiver.ChannelHandler(YOUR_PROTOCOL);
dashHandler.addChannelFactory(receiver.createChannelFactory(YOUR_PROTOCOL));
dashHandler.addEventListener(cast.receiver.Channel.EventType.MESSAGE, onMessage.bind(this));
receiver.start();
...
onMessage = function (e) {
var message = e.message;
switch (message.type) {
...
}
}
On the sender, after a session is created you will want to send a check status message to the receiver to see if there are already channels attached. You can do this via your MessageStream and your receiver needs to respond in such a way that the MessageStream gets its status updated. You check that status to see if there are channels. If there are you can start listening to updates for your receiver. If not you can send a load event to the receiver to start your activity.
MediaProtocolCommand cmd = mMessageStream.requestStatus();
cmd.setListener(new MediaProtocolCommand.Listener() {
#Override
public void onCompleted(MediaProtocolCommand mPCommand) {
if (mMessageStream.getState() == 'channelsExist') {
//Start New Activity
} else {
//Join Existing Activity
}
#Override
public void onCancelled(MediaProtocolCommand mPCommand) {
}
});
This is kind of a vague response, but it could be more specific if I knew what you were trying to do. My app is using Google's RAMP protocol to play videos so my MessageStream and all it's messages are already defined. If you're doing something different, you need to create your own MessageStream.
Sorry for the late answer, but I figured it out by myself: It wasn't such complicated at all
I started the an Application like this
try {
mSession.startSession(applicationName,applicationArgs);
} catch (IllegalStateException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
} catch (IOException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
}
But it seems, that the MimeData applicationArgs is not needed at all. By removing the arguments and starting the session like below it works really fine!
try {
mSession.startSession(applicationName);
} catch (IllegalStateException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
} catch (IOException e) {
Log.e(getClass().getSimpleName(), e.getMessage(), e);
}
I hope this works for you too!