Iam implementing FCM push notification using PHP script and below code, I want to send notification to all device which subscribed to topic with name (news), but when call my script no message recieved and i donnt know what is wrong
public override void OnMessageReceived(RemoteMessage message)
{
base.OnMessageReceived(message);
SendNotificatios(message.GetNotification().Body, message.GetNotification().Title);
}
public void SendNotificatios(string body, string Header)
{
Notification.Builder builder = new Notification.Builder(this);
builder.SetSmallIcon(Resource.Drawable.Icon);
var intent = new Intent(this, typeof(MainActivity));
intent.AddFlags(ActivityFlags.ClearTop);
PendingIntent pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
builder.SetContentIntent(pendingIntent);
builder.SetSmallIcon(Resource.Drawable.Icon);
builder.SetContentTitle(Header);
builder.SetContentText(body);
builder.SetDefaults(NotificationDefaults.Sound);
builder.SetAutoCancel(true);
NotificationManager notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.Notify(1, builder.Build());
}
}
}
MainActivity
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
msgText = FindViewById<TextView>(Resource.Id.msgText);
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Log.Debug(TAG, "Key: {0} Value: {1}", key, value);
}
}
IsPlayServicesAvailable();
var logTokenButton = FindViewById<Button>(Resource.Id.logTokenButton);
logTokenButton.Click += delegate
{
Log.Debug(TAG, "InstanceID token: " + FirebaseInstanceId.Instance.Token);
};
var subscribeButton = FindViewById<Button>(Resource.Id.subscribeButton);
subscribeButton.Click += delegate
{
FirebaseMessaging.Instance.SubscribeToTopic("test");
Log.Debug(TAG, "Subscribed to remote notifications");
};
}
Manifest file
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.amgad.android" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="15" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application android:label="FCM">
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdInternalReceiver" android:exported="false" />
<receiver android:name="com.google.firebase.iid.FirebaseInstanceIdReceiver" android:enabled="true" 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="${applicationId}" /> </intent-filter>
</receiver>
</application>
Related
I am trying to implement in-app purchases, and have followed the documentation to the letter.
The app was published in the store with in-app purchases enabled. Our store account has active products and subscriptions, but trying to buy with ~20 different accounts, we all get "Your order could not be processed. Please try again". after inputting credit card info.
I triple checked our public key for the store and our purchases IDs. Using the Google test IDs, the app works. In-app purchases worked ~6 months ago.
These are the 2 errors I see in my device log:
purchasefragment error purchaseerror type 2 subtype 0
unexpected response code 500 for https://android.clients.google.com/fdfe/ees/commitPurchase
We have written the app in Xamarin and are using the Xamarin.InAppBilling component.
private InAppBillingServiceConnection _serviceConnection;
private IEnumerable<Product> _availableProducts;
//public event EventHandler<PurchaseCanceledEventArgs> PurchaseCanceled;
public event EventHandler<PurchaseFailedEventArgs> PurchaseFailed;
public event EventHandler<PurchaseSucceededEventArgs> PurchaseSucceeded;
public void Buy(string productId)
{
if (_serviceConnection.Connected)
{
if (_availableProducts != null && _availableProducts.Any())
{
var product = _availableProducts.FirstOrDefault(x => x.ProductId.Equals(productId));
if (product != null)
{
_serviceConnection.BillingHandler.BuyProduct(product);
}
}
}
}
public PurchaseProduct GetProduct(string productId)
{
return null;
}
public bool HasSubscriptionFor(string productIdentifier)
{
if (_serviceConnection?.BillingHandler != null)
{
return _serviceConnection.BillingHandler.GetPurchases(ItemType.Subscription).Any(x => x.ProductId == productIdentifier);
}
return false;
}
public void RestorePreviousPurchases()
{
// Restore not required for google purchases (?)
}
public void Disconnect()
{
try
{
_serviceConnection?.Disconnect();
}
catch (Exception ex)
{
}
}
public void Connect(Activity activity)
{
try
{
_serviceConnection = new InAppBillingServiceConnection(activity, "our public key");
_serviceConnection.OnConnected += OnConnected;
_serviceConnection.Connect();
}
catch (Exception ex)
{
}
}
private async void OnConnected()
{
await Task.Run(async () =>
{
if (_serviceConnection?.BillingHandler != null)
{
_serviceConnection.OnInAppBillingError += OnInAppBillingError;
_serviceConnection.BillingHandler.OnProductPurchased += BillingHandlerOnOnProductPurchased;
_serviceConnection.BillingHandler.OnProductPurchasedError += BillingHandlerOnOnProductPurchasedError;
_serviceConnection.BillingHandler.BuyProductError += BillingHandlerOnBuyProductError;
// Test in sandbox mode only
//_availableProducts = await _serviceConnection.BillingHandler.QueryInventoryAsync(new List<string>
//{
// ReservedTestProductIDs.Purchased,
// ReservedTestProductIDs.Refunded,
// ReservedTestProductIDs.Canceled,
// ReservedTestProductIDs.Unavailable
//}, ItemType.Product);
var products = await _serviceConnection.BillingHandler.QueryInventoryAsync(_purchaseConfiguration.Products, ItemType.Product);
var subscriptions = await _serviceConnection.BillingHandler.QueryInventoryAsync(_purchaseConfiguration.Subscriptions, ItemType.Subscription);
_availableProducts = new List<Product>();
if (products?.Any() == true)
{
_availableProducts = _availableProducts.Concat(products);
}
if (subscriptions?.Any() == true)
{
_availableProducts = _availableProducts.Concat(subscriptions);
}
}
});
}
public void HandleResult(int requestCode, object resultCode, object data)
{
_serviceConnection.BillingHandler.HandleActivityResult(requestCode, (Result)resultCode, (Intent)data);
}
private void BillingHandlerOnBuyProductError(int responseCode, string sku)
{
PurchaseFailed?.Invoke(this, new PurchaseFailedEventArgs { Message = "BillingHandlerOnBuyProductError: " + sku });
}
private void BillingHandlerOnOnProductPurchasedError(int responseCode, string sku)
{
PurchaseFailed?.Invoke(this, new PurchaseFailedEventArgs { Message = "BillingHandlerOnBuyProductError: " + sku });
}
private void BillingHandlerOnOnProductPurchased(int response, Purchase purchase, string purchaseData, string purchaseSignature)
{
PurchaseSucceeded?.Invoke(this, new PurchaseSucceededEventArgs(purchase.ProductId));
}
private void OnInAppBillingError(InAppBillingErrorType error, string message)
{
if (!string.IsNullOrEmpty(message))
{
PurchaseFailed?.Invoke(this, new PurchaseFailedEventArgs { Message = message });
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="3.0.14" package="">
<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="23" />
<application android:label="" android:icon="#drawable/ic_launcher" android:theme="#style/ApplicationBaseTheme" android:largeHeap="true" android:allowBackup="false">
<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="%PACKAGE_NAME%" />
</intent-filter>
</receiver>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<service android:name="com.pushwoosh.GCMInstanceIDListenerService" android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="#string/facebook_app_id" />
<meta-data android:name="com.facebook.sdk.ApplicationName" android:value="#string/facebook_app_name" />
</application>
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<permission android:name="%PACKAGE_NAME%.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="%PACKAGE_NAME%.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!--for Samsung-->
<uses-permission android:name="com.sec.android.provider.badge.permission.READ"/>
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE"/>
<!--for htc-->
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS"/>
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT"/>
<!--for sony-->
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE"/>
<!--for apex-->
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT"/>
<!--for solid-->
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE"/>
</manifest>
Working on Wear application, I have created Wear application with Mobile and wear applications. Sending data from mobile application, through "MessageApi.SendMessageResult" and returning status is SUCCESS but message is not received in wear application. Please find the code in below and let me know i am missing any thing.
Mobile App Code:
public class MainActivity extends Activity implements GoogleApiClient.ConnectionCallbacks {
private static final String START_ACTIVITY = "/start_activity";
private static final String WEAR_MESSAGE_PATH = "/message";
private GoogleApiClient mApiClient;
private ArrayAdapter<String> mAdapter;
private ListView mListView;
private EditText mEditText;
private Button mSendButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
initGoogleApiClient();
}
private void initGoogleApiClient() {
mApiClient = new GoogleApiClient.Builder( this )
.addApi( Wearable.API )
.build();
mApiClient.connect();
}
#Override
protected void onDestroy() {
super.onDestroy();
mApiClient.disconnect();
}
private void init() {
mListView = (ListView) findViewById( R.id.list_view );
mEditText = (EditText) findViewById( R.id.input );
mSendButton = (Button) findViewById( R.id.btn_send );
mAdapter = new ArrayAdapter<String>( this, android.R.layout.simple_list_item_1 );
mListView.setAdapter( mAdapter );
mSendButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
String text = mEditText.getText().toString();
if (!TextUtils.isEmpty(text)) {
mAdapter.add(text);
mAdapter.notifyDataSetChanged();
sendMessage(WEAR_MESSAGE_PATH, text);
}
}
});
}
private void sendMessage( final String path, final String text ) {
new Thread( new Runnable() {
#Override
public void run() {
//Previous code
NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes( mApiClient ).await();
Log.d("MessageAPI","nodes :: "+nodes);
for(com.google.android.gms.wearable.Node node : nodes.getNodes()) {
Log.d("MessageAPI","nodes for :: "+node);
MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(
mApiClient, node.getId(), path, text.getBytes() ).await();
Log.d("MessageAPI","node.getId() : "+node.getId());
Log.d("MessageAPI","text.getBytes() : "+text.getBytes());
Log.d("MessageAPI","path : "+path);
Log.d("MessageAPI","nodes result Status:: "+result.getStatus().isSuccess());
}
/*PutDataMapRequest putDMR = PutDataMapRequest.create(path);
putDMR.getDataMap().putAll(getDatMap());
PutDataRequest request = putDMR.asPutDataRequest();
DataApi.DataItemResult result = Wearable.DataApi.putDataItem(mApiClient, request).await();
if (result.getStatus().isSuccess()) {
Log.v("MessageAPI", "nodes DataMap: " + getDatMap() + " sent successfully to data layer ");
} else {
// Log an error
Log.v("MessageAPI", "nodes ERROR: failed to send DataMap to data layer");
}*/
runOnUiThread( new Runnable() {
#Override
public void run() {
mEditText.setText( "" );
}
});
}
}).start();
}
#Override
public void onConnected(Bundle bundle) {
sendMessage(START_ACTIVITY, "Wear my TEST MESSAGE");
}
#Override
public void onConnectionSuspended(int i) {
}
private DataMap getDatMap(){
DataMap dataMap = new DataMap();
dataMap.putLong("time", new Date().getTime());
dataMap.putString("hole", "1");
dataMap.putString("front", "250");
dataMap.putString("middle", "260");
dataMap.putString("back", "270");
return dataMap;
}
}
Mobile App manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ptrprograms.wearmessageapi" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<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>
</application>
wearApp Code
public class WearMessageListenerService extends WearableListenerService {
private static final String START_ACTIVITY = "/start_activity";
#Override
public void onMessageReceived(MessageEvent messageEvent) {
Log.d("MessageAPI","onMessageReceived :: "+ messageEvent.getPath());
/* if( messageEvent.getPath().equalsIgnoreCase( START_ACTIVITY ) ) {
Intent intent = new Intent( this, MainActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
} else {
super.onMessageReceived(messageEvent);
}*/
showToast("onMessageReceived:: "+messageEvent.getPath());
Intent intent = new Intent( this, MainActivity.class );
intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK );
startActivity( intent );
}
private void showToast(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
#Override
public void onDataChanged(DataEventBuffer dataEventBuffer) {
super.onDataChanged(dataEventBuffer);
Log.d("MessageAPI","onMessageReceived : onDataChanged: ");
}
}
wearApp manifest:
<?xml version="1.0" encoding="utf-8"?>
<uses-feature android:name="android.hardware.type.watch" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.DeviceDefault" >
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<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>
<!-- <service android:name=".WearMessageListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>-->
<service android:name=".WearMessageListenerService">
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<data android:scheme="wear" android:host="*" android:pathPrefix="/prefix" />
<!--<data android:scheme="wear" android:host="*"
android:path="/start_activity" />-->
<!--<action android:name="com.google.android.gms.wearable.CAPABILITY_CHANGED" />
<action android:name="com.google.android.gms.wearable.CHANNEL_EVENT" />-->
<!-- <data android:scheme="wear" android:host="*" android:path="/start_activity" />-->
</service>
</application>
1) Problem is in wearApp in WearMessageListenerService. You don't call
super.onMessageReceived(messageEvent);
i.e you consume all messages. When you call super method you pass message to Wearable.MessageApi.addListener(...
2) I don't see in your wear app that you register MessageApi listener.
3) You mix MessageApi with Data Layer api.
4) In wear app in Main activity you need connect with google play services too. To register MessageApi listener in onConnected method.
5) Please check https://github.com/mariopce/android-wear-bilateral-communication.
This is example of using MessageApi for 2-way communication (mobile-wear-mobile)
I'm able to get the registration token id from gcm but my problem is that when i send the message to the client app i don't receive it on Xamarin Android Player. I followed the example on this site : https://developer.xamarin.com/guides/cross-platform/application_fundamentals/notifications/android/remote_notifications_in_android/
Here is my code :
MainActivity.cs
[Activity(Label = "ResApp", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
TextView msgText;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
msgText = FindViewById<TextView>(Resource.Id.msgText);
if (IsPlayServicesAvailable()) //this check if google play is installed
{
var intent = new Intent(this, typeof(RegistrationIntentService));
StartService(intent);
}
}
public bool IsPlayServicesAvailable()
{
int resultCode = GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.Success)
{
if (GoogleApiAvailability.Instance.IsUserResolvableError(resultCode))
msgText.Text = GoogleApiAvailability.Instance.GetErrorString(resultCode);
else
{
msgText.Text = "Sorry, this device is not supported";
Finish();
}
return false;
}
else
{
msgText.Text = "Google Play Services is available.";
return true;
}
}
}
RegistrationIntentService.cs
[Service(Exported = false)]
class RegistrationIntentService : IntentService
{
static object locker = new object();
public RegistrationIntentService() : base("RegistrationIntentService") { }
protected override void OnHandleIntent(Intent intent)
{
try
{
Log.Info("RegistrationIntentService", "Calling InstanceID.GetToken");
lock (locker)
{
var SenderID = "xxxxx";
var instanceID = InstanceID.GetInstance(this);
var token = instanceID.GetToken(SenderID, GoogleCloudMessaging.InstanceIdScope, null);
Log.Info("RegistrationIntentService", "GCM Registration Token: " + token);
SendRegistrationToAppServer(token);
Subscribe(token);
}
}
catch (Exception e)
{
Log.Debug("RegistrationIntentService", "Failed to get a registration token");
return;
}
}
void SendRegistrationToAppServer(string token)
{
// Add custom implementation here as needed.
}
void Subscribe(string token)
{
var pubSub = GcmPubSub.GetInstance(this);
pubSub.Subscribe(token, "/topics/global", null);
}
}
InstanceIdListenerService.cs
[Service(Exported = false), IntentFilter(new[] { "com.google.android.gms.iid.InstanceID" })]
class MyInstanceIDListenerService : InstanceIDListenerService
{
public override void OnTokenRefresh()
{
var intent = new Intent(this, typeof(RegistrationIntentService));
StartService(intent);
}
}
GcmListenerService.cs
[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.ic_stat_ic_notification)
.SetContentTitle("GCM Message")
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingIntent);
var notificationManager = (NotificationManager)GetSystemService(Context.NotificationService);
notificationManager.Notify(0, notificationBuilder.Build());
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="co.za.resapp" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:label="ResApp"></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="co.za.resapp.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEGED" />
<permission android:name="co.za.resapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<application android:label="CodeLog">
<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="co.za.resapp" />
</intent-filter>
</receiver>
</application>
</manifest>
Send Message from Server
var jGcmData = new JObject();
var jData = new JObject();
jData.Add("message", MESSAGE);
jGcmData.Add("to", "/topics/global");
jGcmData.Add("data", jData);
var url = new Uri("https://gcm-http.googleapis.com/gcm/send");
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "key=" + API_KEY);
Task.WaitAll(client.PostAsync(url,
new StringContent(jGcmData.ToString(), Encoding.Default, "application/json"))
.ContinueWith(response =>
{
Console.WriteLine(response);
Console.WriteLine("Message sent: check the client device notification tray.");
}));
}
}
catch (Exception ex)
{
Console.WriteLine("Unable to send GCM message:");
Console.Error.WriteLine(ex.StackTrace);
}
It seems like there was a problem in the manifest file. I pasted this new code in the manifest code and the program worked :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="co.za.resapp" android:versionCode="1" android:versionName="1.0" android:installLocation="auto">
<uses-sdk android:minSdkVersion="11" />
<application android:label="GCM_ANDROID">
<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="co.za.resapp" />
</intent-filter>
</receiver>
</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="co.za.resapp.permission.C2D_MESSAGE" />
</manifest>
How to get push notification working after manually closing UI on Android?
Hi, I need some help, Couldn't find any solutions by searching.
Application basically is like any other messaging applications, ex. Whatsapp.
I have MessageService running as own process, even UI closed, it stays alive.
This is how my application basically works:
MainActivity start service
MessageService send broadCast to
messageReceiver gets broadCast and run messageLoader
MessagesLoader extends AsyncTask gets changes from database
MessagesLoader push notification.
Every these parts working correctly when UI running
When I close UI, messageService restarts again, but no push notifications after UI closed.
Any help to get this work would be appreciated.
Thanks
Here is some code snippet to understand how my thing works..
MainActivity.java
...........................
#Override
protected void onResume() {
super.onResume();
serviceIntent = new Intent(getApplicationContext(), MessageService.class);
startService(serviceIntent);
registerReceiver(messageReceiver, new IntentFilter(MessageService.MESSAGES_BROADCAST_ACTION));
}
...........................
MessageService.java
public class MessageService extends Service {
Updater updater;
BroadcastReceiver messageBroadcaster;
Intent intent;
Context context;
static final public String MESSAGES_BROADCAST_ACTION = "com.<Your Package>";
public MessageService() {
}
#Override
public IBinder onBind(Intent intent) {
this.intent = intent;
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
this.updater = new Updater();
this.context = getApplicationContext();
this.intent = new Intent(this, NotificationActivity.class);
Toast.makeText(this, "Message Service Created", Toast.LENGTH_LONG).show();
}
#Override
public synchronized int onStartCommand(Intent intent, int flags, int startId) {
if (!updater.isRunning()) {
updater.start();
updater.isRunning = true;
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public synchronized void onDestroy() {
super.onDestroy();
if (updater.isRunning) {
updater.interrupt();
updater.isRunning = false;
updater = null;
}
Toast.makeText(this, "Message Service Destroyed", Toast.LENGTH_LONG).show();
}
class Updater extends Thread {
public boolean isRunning = false;
public long DELAY = 2500;
#Override
public void run() {
super.run();
isRunning = true;
while (isRunning) {
sendResult();
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
e.printStackTrace();
isRunning = false;
}
}
}
public boolean isRunning() {
return this.isRunning;
}
}
public void sendResult() {
sendBroadcast(intent);
}
}
MessageReceiver.java
public class MessageReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent(context, MessageService.class);
context.startService(serviceIntent);
new MessagesLoader(context).execute();
}
}
MessageLoader.java
public class MessagesLoader extends AsyncTask<String,Void,String> {
public MessagesLoader(Context context) {
this.context = context;
this.intent = new Intent(this.context, ChatsActivity.class);
this.prev_count = prev_count;
Intent intent = new Intent(context, ChatsActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0, intent, 0);
this.mBuilder = new android.support.v4.app.NotificationCompat.Builder(context)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("YOUR APP");
}
protected void onPreExecute(){
}
#Override
protected String doInBackground(String... arg0) {
StringBuffer result = new StringBuffer("");
try {
URL url = new URL("http://yourURL.com/get_data.php");
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
con.setDoOutput(true);
String urlParameters = "<OWN PARAMETERS>";
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
con.connect();
InputStream inputStream = con.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
return new String(result);
} catch(Exception e){
return new String("Exception: " + e.getMessage());
}
}
#Override
protected void onPostExecute(String result) {
initData(result);
}
public void initData(String result) {
// Actually Store Data to sharedPreferences
String error = "";
JSONObject obj = new JSONObject();
// ...ETC
int count = 5;
showNotification(5);
}
public void showNotification(int count) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent mIntent = new Intent(this.context, ChatsActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this.context, 0, mIntent, 0);
Intent cIntent = new Intent(this.context, NotificationActionService.class);
PendingIntent cPIntent = PendingIntent.getService(this.context, 0, cIntent, 0);
NotificationCompat.BigTextStyle bigTextStyle = new NotificationCompat.BigTextStyle();
bigTextStyle.bigText("YOUR BIG TEXT");
Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
mBuilder
.setContentIntent(pIntent)
.setContentText("YOUR CONTENT TEXT")
.setAutoCancel(true)
.setLights(R.color.white, 1000, 500)
.setSound(soundUri)
.setGroup("YOUR GROUP")
.setTicker("YOUR TICKER TEXT")
.setWhen(System.currentTimeMillis())
.setCategory("YOUR CATEGORY")
.setStyle(bigTextStyle)
.addAction(0, "Show Messages", pIntent);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(mIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourpackage" >
android:versionCode="1"
android:versionName="1.0"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:configChanges="orientation"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.yourpackage.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<service android:name="com.yourpackage.MessageService"
android:process=":messageService"
android:enabled="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/messageService">
<intent-filter>
<action android:name="com.yourpackage.MessageService" />
</intent-filter>
</service>
<receiver android:name="com.yourpackage.MessageReceiver">
<intent-filter>
<action android:name="com.yourpackage.MessageReceiver" />
</intent-filter>
</receiver>
</application>
</manifest>
I've found the solution. Now my application is always showing me new messages info even without UI running.
Here is solution to fix this problem.
MainActivity.java
#Override
protected void onResume() {
super.onresume();
serviceIntent = new Intent(getApplicationContext(), MessageService.class);
startService(serviceIntent);
/* COMMENTED OUT LINE BELOW */
//registerReceiver(messageReceiver, new IntentFilter(MessageService.MESSAGES_BROADCAST_ACTION));
}
MessageService.java
#Override
public void onCreate() {
super.onCreate();
updater = new Updater();
context = getApplicationContext();
/* AND ADDED THAT LINE HERE AND */
registerReceiver(messageReceiver, new IntentFilter(MESSAGES_BROADCAST_ACTION));
intent = new Intent(MESSAGES_BROADCAST_ACTION);
Toast.makeText(this, "Message Service Created", Toast.LENGTH_LONG).show();
}
This is my sms receiver
package com.example.smsTest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
//---get the SMS message passed in---
Bundle bundle = intent.getExtras();
SmsMessage[] msgs = null;
String str = "";
if (bundle != null)
{
//---retrieve the SMS message received---
Object[] pdus = (Object[]) bundle.get("pdus");
msgs = new SmsMessage[pdus.length];
for (int i=0; i<msgs.length; i++){
msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
str += "SMS from " + msgs[i].getOriginatingAddress();
str += " :";
str += msgs[i].getMessageBody().toString();
str += "\n";
}
Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
Intent mainActivityIntent = new Intent(context, SMSTest.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mainActivityIntent);
//---send a broadcast intent to update the SMS received in the activity---
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("SMS_RECEIVED_ACTION");
broadcastIntent.putExtra("sms", str);
context.sendBroadcast(broadcastIntent);
}
}
}
This is manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smsTest"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="4"
android:targetSdkVersion="8"
android:maxSdkVersion="8" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".SMSTest"
android:label="#string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".SmsReceiver">
<intent-filter android:priority="99999">
<action android:name="android.provider.telephony.SMS_RECIEVED"></action>
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.SEND_SMS">
</uses-permission>
<uses-permission android:name="android.permission.RECEIVE_SMS">
</uses-permission>
enter code here
</manifest>
I want to call the another class named as SMSText.class from above SmsReceiver class. I wrote the above but its not working.
In SmsReceiver do the following:
Intent mainActivityIntent = new Intent(context, SMSTest.class);
mainActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mainActivityIntent.putExtra("sms", str);
context.startActivity(mainActivityIntent);
Then, in the Activity's onCreate() method:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView SMSes = (TextView) findViewById(R.id.textView1);
String sms = getIntent().getStringExtra("sms");
SMSes.setText(sms);
}
You've misspelled "RECEIVED" in the <intent-filter> in your manifest, so your BroadcastReceiver isn't firing. It should be:
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
String activity= "android.provider.telephony.SMS_RECIEVED";
Intent mainActivityIntent = new Intent(activity);
startActivity(mainActivityIntent);