Push Notifications not working using GCM - google-cloud-messaging

We have a android application development in progress, where in we are supposed to go for Topic Messaging using GCM (C#).
We have Created Entries in Google Developer Console to enable Cloud Messaging for our Android App and have got API Key + Sender ID + Server Key + Browser Key.
We have written the Server Side Implementation in a console Application/ASMX Web Service to check the Push using API Key/Browser Key + Sender ID + Topic name and we have been successful in getting the MessageID/Multicast ID from GCM.
At Client End, we have handled as per the documentation provided at xamarin for Android and placed Listener Services (Registration, Intent, GCM ) properly by using SenderID + Topicname. We are getting Registration Token and have subscribed to a topic as well as documented.
But we are currently not getting push notification at the client end. Is it something which we have missed in the implementation part? Kindly Suggest.
Android Manifest File:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xamarin.gcmexample" android:versionCode="1" android:versionName="1.0">
<uses-sdk />
<application android:label="Notifications" android:icon="#drawable/Icon"></application>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.xamarin.gcmexample.permission.C2D_MESSAGE" />
<permission android:name="com.xamarin.gcmexample.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application android:label="Notifications" android:icon="#drawable/Icon">
<receiver android:name="com.google.android.gms.gcm.GcmReceiver" android:exported="true" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.xamarin.gcmexample" />
</intent-filter>
</receiver>
<service android:name="com.example.MyGcmListenerService" android:exported="false">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service android:name="com.example.MyInstanceIDListenerService" android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
</application>
</manifest>
GCMReceiver Code
[Service(Exported = false), IntentFilter(new[] { "com.google.android.c2dm.intent.RECEIVE" })]
public class MyGcmListenerService : GcmListenerService
{
public override void OnMessageReceived(string from, Bundle data)
{
var message = data.GetString("message");
Log.Debug("MyGcmListenerService", "From: " + from);
Log.Debug("MyGcmListenerService", "Message: " + message);
SendNotification(message);
}
void SendNotification(string message)
{
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
var pendingIntent = PendingIntent.GetActivity(this, 0, intent, PendingIntentFlags.OneShot);
var notificationBuilder = new Notification.Builder(this)
.SetSmallIcon(Resource.Drawable.Icon)
.SetContentTitle("GCM Message")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(0, notificationBuilder.Build());
}
}

Related

React native fetch/axios api calls always goes to catch

I have tried using both fetch and axios. But both of these calls fail in my react-native application. It always goes into the catch function. Though calling this api from the browser or from Postman works fine.
axios.get('http://sahajdevapi.letsendorse.com')
.then(function (response) {
console.warn("res 1: ", response);
}).catch(function (error) {
console.warn("err 1: ", error);
});
The error that I get from the catch function is as follows:
'err:', { [TypeError: Network request failed]
line: 24115,
column: 31,
sourceURL: 'http://localhost:8081/index.delta?platform=android&dev=true&minify=false'}
For newer version you need to add some security for http access.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:name=".MainApplication"
android:allowBackup="false"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#drawable/ic_launcher_round"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning">
<uses-library
android:name="org.apache.http.legacy"
android:required="false" />
<activity
android:name=".MainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:label="#string/app_name"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
Check your file you need to add in manifest tag tools and uses-library for that.
Try this one it will work.
As android VM is an emulator If we use localhost then its points to local host of the android emulator system but not localhost of the development system. So use system IP address instead of localhost

can't detect notification when app closed

so I've been trying to do this app but for some reason, after I can't seem to be able to detect notification from the firebase consol when the app is closed (not in the background or frontground those work fine).
so here are some of the relevant files.
componentDidMount() {
this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
// Process your notification as required
// ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
});
this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
// Process your notification as required
notification.android.setChannelId('test-channel')
console.log("I'm called haha", notification);
firebase.notifications().displayNotification(notification)
});
this.messageListener = firebase.messaging().onMessage((message) => {
bgMessaging(message)
})
}
componentWillUnmount() {
this.notificationDisplayedListener();
this.notificationListener();
}
android manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mobalib">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:allowBackup="false"
android:theme="#style/AppTheme">
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
<receiver android:name="io.invertase.firebase.notifications.RNFirebaseBackgroundNotificationActionReceiver"
android:exported="true">
<intent-filter>
<action android:name="io.invertase.firebase.notifications.BackgroundAction"/>
</intent-filter>
</receiver>
</service>
<service
android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<activity
android:launchMode="singleTop"
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
index.js:
AppRegistry.registerHeadlessTask('RNFirebaseBackgroundMessage', () => bgMessaging);
and finaly bgMesseging.js:
xport default (message: RemoteMessage) => {
// handle your message
const title = message.get
const notification = new firebase.notifications.Notification()
.setNotificationId('notificationId')
.setTitle('My notification title')
.setBody('My notification body')
.setData({
key1: 'value1',
key2: 'value2',
});
notification
.android.setChannelId('test-channel')
firebase.notifications().displayNotification(notification)
console.log(message);
return Promise.resolve();
}
the TL/dr is that depending on what brand your phone is the notification can only be detected.
so Android not that great when it comes to this part of notification but it is so customisable on other thing that i do like it

Splash screen on Android

I have a problem with the splashscreen on Android. Here is everything what I am doing:
Creating background_splash.xml file:
xml version="1.0" encoding="utf-8"?>
layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="#android:color/darker_gray"/>
<item>
<bitmap
android:gravity="center"
android:src="#drawable/splash"/>
</item>
I remove < in the first two lines because stackoverflow cannot display them. This file is located in drawable.
I added the following to styles.xml:
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
<item name="android:windowBackground">#drawable/background_splash</item>
</style>
and this is my manifest files:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="22" />
<application
android:name=".MainApplication"
android:allowBackup="true"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:theme="#style/AppTheme">
<activity
android:name=".SplashActivity"
android:label="#string/app_name"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" />
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
</application>
</manifest>
And also the activity:
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
public class SplashActivity extends ReactActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish();
}
}
This is the error I have:
Starting the app on 51d123cc (adb -s 51d123cc shell am start -n com.test/.MainActivity)...
Starting: Intent { cmp=com.test/.MainActivity }
java.lang.SecurityException: Permission Denial: starting Intent { flg=0x10000000 cmp=com.test/.MainActivity } from null (pid=20601, uid=2000) not exported from uid 11152
at android.os.Parcel.readException(Parcel.java:1540)
at android.os.Parcel.readException(Parcel.java:1493)
at android.app.ActivityManagerProxy.startActivityAsUser(ActivityManagerNative.java:2589)
at com.android.commands.am.Am.runStart(Am.java:768)
at com.android.commands.am.Am.onRun(Am.java:307)
at com.android.internal.os.BaseCommand.run(BaseCommand.java:47)
at com.android.commands.am.Am.main(Am.java:102)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:255)
UPDATE:
To the answer of #Ankit Prajapati I will add also that I set
android:largeHeap="true"
which was an error from Android Studio (running from the terminal this error wasn't reported) and this happen after changing activity to SplashActivity.
Also it was necessary to change edit configurations and changing "Launch Activity" to "Specified Activity" and setting com.test.SplashActivity.
Second way of managing splash screen on Android and which I use right now is with this tutorial:
Splash Screen Android
Try using this in
android:exported="true" in the manifest file in the activity you are trying to start (Loading Activity)
Like this
<activity
android:name=".SplashActivity"
android:label="#string/app_name"
android:theme="#style/SplashTheme"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Also Add
Intent intent = new Intent(SplashActivity.this, MainActivity.class);

GcmBroadcastReceiver - GcmListenerService

Could someone explain to me how the GCM receiver works in the following example. By setting at
gcm_receiver name = "com.google.android.gms.gcm.GcmReceiver"
and in category my package what do I achieve? Does it mean that GCM messages are received from GCM receiver (without writing any code) and delivered to my app, where my GCM listener receives them?
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="gcm.play.android.samples.com.gcmquickstart" >
<uses-permission android:name="android.permission.INTERNET" />
<!-- [START gcm_permission] -->
<permission android:name="gcm.play.android.samples.com.gcmquickstart.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="gcm.play.android.samples.com.gcmquickstart.permission.C2D_MESSAGE" />
<!-- [END gcm_permission] -->
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- [START gcm_receiver] -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="gcm.play.android.samples.com.gcmquickstart" />
</intent-filter>
</receiver>
<!-- [END gcm_receiver] -->
<!-- [START gcm_listener] -->
<service
android:name="gcm.play.android.samples.com.gcmquickstart.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="gcm.play.android.samples.com.gcmquickstart.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name=".RegistrationIntentService"
android:exported="false">
</service>
</application>
</manifest>
From com.google.android.gms.gcm, GcmReceiver was described as WakefulBroadcastReceiver that receives GCM messages and delivers them to an application-specific GcmListenerService subclass.
Likewise, as also discussed in Set up a GCM Client App on Android, in editing your application's Manifest:
GcmReceiver handles messages sent from GCM to your application.
GcmListenerService enables various aspects of handling messages such as detecting different downstream message types, determining upstream send status, and automatically displaying simple notifications on the app’s behalf.
InstanceIDListenerService handles the creation, rotation, and updating of registration tokens.
Checking the documentation will help you to understand how GCM Client App works on Android.

SecurityException: Not allowed to start service Intent REGISTER without permission on Android 5

after updating my device to Android 5, I get the following exception when starting my app:
Caused by: java.lang.SecurityException: Not allowed to start service Intent { act=com.google.android.c2dm.intent.REGISTER pkg=com.google.android.gms (has extras) } without permission com.google.android.c2dm.permission.RECEIVE
My manifest should look correct:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="custom.package"
android:versionCode="7"
android:versionName="1.5.0">
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="custom.package.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="custom.package.permission.C2D_MESSAGE" />
<!-- This app has permission to register with GCM and receive message -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.google.android.c2dm.permission.SEND" />
<application
...
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="custom.package" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
What am I missing? On Android <= 4 everything works as expected.
Have you put <service> tag in your Manifest?
Try to compare following AndroidManifest.xml to see where went wrong:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="custom.package"
android:versionCode="7"
android:versionName="1.5.0">
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="app.cloudstringers.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission
android:name="app.cloudstringers.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="app.cloudstringers.Cloudstringers"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="ui.fragment.RegisterWithAccountsFragment" />
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<!-- Receiver GCM -->
<receiver
android:name="app.cloudstringers.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="app.cloudstringers" />
</intent-filter>
</receiver>
<!-- Service GCM -->
<service
android:exported="true"
android:name="app.cloudstringers.GcmIntentService" />
</application>
</manifest>
The design was changed from Lollipop.
Please refer to the change.
Android 5.0 includes a behavior change to ensure that only one app can define a given custom permission, unless signed with the same key as other apps defining the permission.