I am sending the push notifications with the help of Urban Airship, and getting the notifications successfully also. But when I am clicking on the notification, it is not opening my app. So what can I do for opening my app ?
and getting the following error in logcate:-
02-10 18:53:44.137: W/xxx - UALib(6840): Activity com.aaa.yyy.SplashActivity#40dcb458 was not manually added during onStart(). Call UAirship.shared().getAnalytics().activityStarted in every activity's onStart() method.
Yes after doing the Google I got the answer:-
We need to create an IntentReceiver.java class as follows:-
public class IntentReceiver extends BroadcastReceiver{
private static final String logTag = "PushSample";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(logTag, "Received intent: " + intent.toString());
String action = intent.getAction();
if (action.equals(PushManager.ACTION_PUSH_RECEIVED)) {
int id = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, 0);
Log.i(logTag, "Received push notification. Alert: "
+ intent.getStringExtra(PushManager.EXTRA_ALERT)
+ " [NotificationID="+id+"]");
logPushExtras(intent);
}else if (action.equals(PushManager.ACTION_NOTIFICATION_OPENED)) {
Log.i(logTag, "User clicked notification. Message: " + intent.getStringExtra(PushManager.EXTRA_ALERT));
logPushExtras(intent);
Intent launch = new Intent(Intent.ACTION_MAIN);
launch.setClass(UAirship.shared().getApplicationContext(), MainActivity.class);
launch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
UAirship.shared().getApplicationContext().startActivity(launch);
}else if (action.equals(PushManager.ACTION_REGISTRATION_FINISHED)) {
Log.i(logTag, "Registration complete. APID:" + intent.getStringExtra(PushManager.EXTRA_APID)
+ ". Valid: " + intent.getBooleanExtra(PushManager.EXTRA_REGISTRATION_VALID, false));
}
}
private void logPushExtras(Intent intent) {
Set<String> keys = intent .getExtras().keySet();
for(String key: keys){
List<String> ignoredKeys = (List<String>)Arrays.asList("collapse_key", "from", PushManager.EXTRA_NOTIFICATION_ID,PushManager.EXTRA_PUSH_ID, PushManager.EXTRA_ALERT);
if(ignoredKeys.contains(key)){
continue;
}
Log.i(logTag, "Push Notification Extra: ["+key+" : " + intent.getStringExtra(key) + "]");
} }
}
After that we need to call the following method in PushNotification.java.
Here is the code.
public class PushNotification extends Application{
#Override
public void onCreate() {
AirshipConfigOptions options = AirshipConfigOptions.loadDefaultOptions(this);
options.developmentAppKey = "xxx";
options.developmentAppSecret = "yyy";
options.productionAppKey = "zzz";
options.inProduction= false;
UAirship.takeOff(this, options);
PushManager.enablePush();
String apid = PushManager.shared().getAPID();
Logger.info("My Application onCreate - App APID: " + apid);
PushManager.shared().setIntentReceiver(IntentReceiver.class);
}
}
In response to your logcat error:
UALib(6840): Activity com.aaa.yyy.SplashActivity#40dcb458 was not manually added during onStart(). Call UAirship.shared().getAnalytics().activityStarted in every activity's onStart() method.
By default, Urban Airship turns on analyticsEnabled in the AirshipConfigOptions (see documentation).
Prior to Android API 14, you had to manually call activityStarted() in every activity's onStart() method (as the logcat warning suggests or see documentation). If your app’s minSDKVersion >= 14 (Ice Cream Sandwich), you no longer need to modify any of your activities. Make sure to set the minSDKVersion in the airshipconfig.properties in order to prevent any missing instrumented analytic warnings.
If you would like to manually instrument your class, update your Activity’s onStart and onStop methods with the following:
#Override
public void onStart() {
super.onStart();
Analytics.activityStarted(this);
}
#Override
public void onStop() {
super.onStop();
Analytics.activityStopped(this);
}
Note:
According to the UA v4 to v5 migration guide the methods to report activity started and stopped are now static (which is the sample code above). If you need to support an older version of UA, then you'd use the sample code from logcat:
UAirship.shared().getAnalytics().activityStarted(this);
Related
I'm fighting against the NotificationListenerService without much luck.
I tried a lot of recipes found here and there, especially on so... But it works quite inconsistently.
A first look at the code :
Manifest :
<service
android:name=".services.NLService"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Then the service itself :
public class NLService extends NotificationListenerService {
private String TAG = "NLService";
// bind and unbind seems to make it work with Android 6...
// but is never called with Android 4.4...
#Override
public IBinder onBind(Intent mIntent) {
IBinder mIBinder = super.onBind(mIntent);
Log.i(TAG, "onBind");
return mIBinder;
}
#Override
public boolean onUnbind(Intent mIntent) {
boolean mOnUnbind = super.onUnbind(mIntent);
Log.i(TAG, "onUnbind");
isNotificationAccessEnabled = false;
try {
} catch (Exception e) {
Log.e(TAG, "Error during unbind", e);
}
return mOnUnbind;
}
// onCreate is called with Android 4.4
// because the service is explicitly started from the MainActivity.
// Not on Android 6 where the system binds this service itself...
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "********** onCreate");
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
Log.i(TAG, "********** onNotificationPosted");
Log.i(TAG, "ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
}
#Override
public void onNotificationRemoved(StatusBarNotification sbn) {
Log.i(TAG, "********** onNOtificationRemoved");
Log.i(TAG, "ID :" + sbn.getId() + "\t" + sbn.getNotification().tickerText + "\t" + sbn.getPackageName());
}
}
And in the main Activity the service is started or we ask the user to enable the setting if needed :
if (!Utilities.hasNotificationAccess(this))
{
Intent intent = new Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS");
startActivity(intent);
Log.i(TAG,"hasNotificationAccess NO");
}
else
{
Log.i(TAG,"hasNotificationAccess YES");
// without this startService, it never works with Android 4.4...
// but this is not needed in Android 6...
Intent mServiceIntent = new Intent(this, NLService.class);
startService(mServiceIntent);
}
Obviously, the secure setting access for notifications is enabled...
On Android 6 :
On the NLService itself, the addition of the onBind and onUnbind methods make it work, I can se the onBind log, and the onNotificationPosted is triggered nicely. But it lasts until the next launch of the app, then no more binding, no more onNotificationPosted, just nothing happens until I go back to security settings to uncheck-recheck the notifications access: repeating this each time the App is started is not something possible in a production environment.
On Android 4.4 :
In contrast to Android 6, in the MainActivity I need to explicitly start the NLService otherwise it never stats by itself. But once again it works for the first launch and never works again until uncheck-recheck the security setting...
Did I miss something obvious ?
There is a problem with Android caching. When you upload app on the device, OS connects your service to Notification Manager. If you ran your app before, Android founds this service in cache so it's not reconnected.
Workaround: before pushing the app on your device, rename your service (refactor option in Android Studio works well) - Android will recognize this service as new one and connect to Notification Manager.
https://developer.android.com/reference/android/service/notification/NotificationListenerService.html#onListenerConnected() - this method will be invoked after connecting to Notification Manager so you can check if your service is connected or not.
I am having an issue getting my ActivityRecognition Service to remain running. I currently have a service (GService) that runs continuously in the background. I want to start the ActivityRecognition service within GService, and have the ActivityRecognition service broadcast the activity result back to GService. I am able to start the service and receive feedback that it is running, and I also get one result from the intent handler (no actual data), but never again.
Here is the section of code from my continuous service setting up the intent, pending intent:
#Override
public void onConnected(Bundle bundle) {
Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
startLocationUpdates();
//start process to receive activity updates
Intent intent = new Intent(this, DetectedActivitiesIntentService.class);
PendingIntent mActivityRecognitionPendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGoogleApiClient, ActivityConstants.DETECTION_INTERVAL_MILLISECONDS_MOVING,
mActivityRecognitionPendingIntent).setResultCallback(this);
startService(intent); // this should start the DetectedActivitiesIntentService
This is the Broadcast receiver within GService:
public class ActivityDetectionBroadcastReceiver extends BroadcastReceiver {
protected static final String TAG_AR = "ADRR";
#Override
public void onReceive(Context context, Intent intent){
//ArrayList<DetectedActivity> updatedActivities =
// intent.getParcelableArrayListExtra(ActivityConstants.ACTIVITY_EXTRA);
//updateDetectedActivitiesList(updatedActivities);
String action = intent.getAction();
if(action.equals("com.gt.useractivity"))
{
Log.d(TAG_AR, "received broadcast from Activity service");
// below line should grab the resulting string activity from the intent and log it.
Log.d(TAG_AR, "activity is : " + intent.getExtras().getString(ActivityConstants.ACTIVITY_EXTRA));
}
}
}
Here is the ActivityRecognition Service code:
public class DetectedActivitiesIntentService extends IntentService {
protected static final String TAG = "ADIS";
/**
* This constructor is required, and calls the super IntentService(String)
* constructor with the name for a worker thread.
*/
public DetectedActivitiesIntentService() {
// Use the TAG to name the worker thread.
super(TAG);
Log.d(TAG, "Activity service started....");
}
#Override
public void onCreate() {
super.onCreate();
}
/**
* Handles incoming intents.
* #param intent The Intent is provided (inside a PendingIntent) when requestActivityUpdates()
* is called.
*/
#Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent))
{
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
Intent localIntent = new Intent(ActivityConstants.BROADCAST_ACTION);
// Get the list of the probable activities associated with the current state of the
// device. Each activity is associated with a confidence level, which is an int between
// 0 and 100.
ArrayList<DetectedActivity> detectedActivities = (ArrayList) result.getProbableActivities();
// Log each activity.
Log.i(TAG, "activities detected");
for (DetectedActivity da: detectedActivities) {
Log.i(TAG, ActivityConstants.getActivityString(da.getType()) + " " + da.getConfidence() + "%");
}
String activity = result.getMostProbableActivity().toString(); // get the activity and convert to string
// Broadcast the list of detected activities.
//localIntent.putExtra(ActivityConstants.ACTIVITY_EXTRA, detectedActivities);
//localIntent.setAction("com.gt.useractivity");
localIntent.putExtra(ActivityConstants.ACTIVITY_EXTRA, activity); // set the activity string to be transmitted
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
else{
Log.d(TAG, "Intent had no activity data....");
}
}
}
This Activity recognition sample is based from the Google Github sample.
All the examples I have found when using the PendingIntent is being called from a main activity, not from a service. I'm obviously doing something incorrect, but I can't figure it out. Any advice would be appreciated. I should also note that I have 2 broadcast receivers within my GService. I don't know if this would cause an issue or not.
It looks like I have solved the problem. I have a second intent within my GService used for broadcasting. From what I can tell from this thread (Pending intent works correctly for first notification but not for the rest) if there are multiple intents being used, they have to be unique. Thus, I added one line of code when declaring my intent intent.setAction(Long.toString(System.currentTimeMillis())); which is enough to differentiate it from the other intent to the system. Once I did that, I began to receive the Activity broadcasts from the intent service, as well as still receiving the location requests from within the GService routine.
I'm adding Urban Airship push notifications to my Android app. My custom BroadcastReceiver is receiving the notifications when I send a test push. Here's the onReceive() method.
public class IntentReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent == null)
return;
String action = intent.getAction();
if (action.equals(PushManager.ACTION_PUSH_RECEIVED)) {
int id = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, 0); //Breakpoint here
Log.w("my app", "Received push notification. Alert: "
+ intent.getStringExtra(PushManager.EXTRA_ALERT)
+ " [NotificationID="+id+"]");
logPushExtras(intent);
} else if (action.equals(PushManager.ACTION_NOTIFICATION_OPENED)) {
//Other stuff here
}
Execution stops at the breakpoint (position shown in the comment) and the details are logged.
No notification is shown in the notification area though. In my other app with UA push notifications, I think this was all I did, but it doesn't seem to be working this time.
I suspect I've done something wrong in my manifest file or that I've forgotten to implement a class somewhere.
Any ideas?
Extra Info
Extended Application:
public class ExtendedApplication extends Application {
public void onCreate(){
AirshipConfigOptions options = AirshipConfigOptions.loadDefaultOptions(this);
UAirship.takeOff(this, options);
PushManager.enablePush();
PushPreferences prefs = PushManager.shared().getPreferences();
Log.e("my app", "My Application onCreate - App APID: " + prefs.getPushId());
PushManager.shared().setIntentReceiver(IntentReceiver.class);
}
}
Edit
I've tried adding
PushManager.shared().setNotificationBuilder(new BasicPushNotificationBuilder());
to my ExtendedApplication as suggested in this post.
I was sending a test push with a blank "Alert" field from the UA site. I tried with some text in there and now it works. I don't know why, but I don't think that's something that should fail silently.
Moral of the story: Don't leave your Alert field blank.
How to change the notification message in Android to localised it?
I just want to change the message what I get from Urban AirShip before it will be display on notification bar?
You can using this method: PushManager.shared().setNotificationBuilder(null); and send your own notification with android notification from the SDK
Yes you can modify the message once you receive the message from Urban AirShip for your internal use in the app but can't show the modified message in the notification bar.
You can check the message in your IntentReceiver
public class IntentReceiver extends BroadcastReceiver {
private static final String logTag = "Hey";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(logTag, "Received intent: " + intent.toString());
String action = intent.getAction();
if (action.equals(PushManager.ACTION_PUSH_RECEIVED)) {
int id = intent.getIntExtra(PushManager.EXTRA_NOTIFICATION_ID, 0);
Log.v(logTag, "Received push notification. Alert: " + intent.getStringExtra(PushManager.EXTRA_ALERT)
+ ". Payload: " + intent.getStringExtra(PushManager.EXTRA_STRING_EXTRA) + ". NotificationID="+id);
//can get your message here
} else if (action.equals(PushManager.ACTION_NOTIFICATION_OPENED)) {
Log.v(logTag, "User clicked notification. Message: " + intent.getStringExtra(PushManager.EXTRA_ALERT)+ ".Payload:" + intent.getStringExtra("PushManager.EXTRA_STRING_EXTRA"));
Intent launch = new Intent(Intent.ACTION_MAIN);
UAirship.shared().getApplicationContext().startActivity(launch);
} else if (action.equals(PushManager.ACTION_REGISTRATION_FINISHED)) {
Log.i(logTag, "Registration complete. APID:" + intent.getStringExtra(PushManager.EXTRA_APID)
+ ". Valid: " + intent.getBooleanExtra(PushManager.EXTRA_REGISTRATION_VALID, false));
}
}
}
I found the solution, its kind a dirty one, but right know I need to use this.
Just after get notification from Urban AirShip I cancel all and send my own with changed message.
I read the answers and came up with a combined solution.
You want to disable UrbanAirship's default notification handler. If you do that, it won't generate and show you the notifications at all.
PushManager.shared().setNotificationBuilder(null); (Using David T's suggestion)
You want to build your own notification. This can be done inside your IntentReceiver. This link will do the trick.
Hope this helps others.
Please using that code to disable Urban Airship's notifications, override BasicPushNotificationBuilder:
BasicPushNotificationBuilder nb = new BasicPushNotificationBuilder() {
#Override
public Notification buildNotification(String alert,
Map<String, String> extras) {
return null;
}
};
// Disable notifications
PushManager.shared().setNotificationBuilder(nb);
I am developing an android application,In my application using Urban Airship for Push notification.It is working fine,I want to if i click on "Notification On" in UI,I will receive Notification to my device,when i click "Notification OFF" in my UI,I will not receive notification to my device.How to implement the code in Urban Airship?How is possible?
Thanks
to enable it
PushManager.enablePush();
and to disable it
PushManager.disablePush();
In your button Click, put this code:
final Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
final ComponentName cn = new ComponentName(
"com.urbanairship.airmail",
"com.urbanairship.airmail.MainListActivity");
intent.setComponent(cn);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Followed by this in your manifest file put this in your <application Tag>:
android:name=".QuadDealsPushReceiver"
Create a QuadDealsPushReceiver.class and put this code:
package com.fsp.quaddeals;
import com.urbanairship.push.APIDReceiver;
import com.urbanairship.push.AirMail;
import com.urbanairship.push.PushReceiver;
import android.app.Application;
import android.content.Intent;
import android.util.Log;
public class QuadDealsPushReceiver extends Application {
public void onCreate(){
AirMail am = AirMail.getInstance();
am.acceptPush(this, new PushReceiver() {
#Override
public void onReceive(String message, String payload){
Log.d("push", "Got message '" + message +"' and payload '" + payload + "'");
}
#Override
public void onClick(String message, String payload){
Log.d("push", "User clicked the notification, got message and payload: "
+ message + ", " + payload);
/* In this example, we fire up our MainActivity class when the
* user clicks the Status Bar Notification. Note that we *must*
* use the flag Intent.FLAG_ACTIVITY_NEW_TASK to start a new
* activity because this callback is fired from within a
* BroadcastReceiver.
**/
Intent intent = new Intent("android.intent.action.MAIN");
intent.setClass(QuadDealsPushReceiver.this, SplashMain.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
QuadDealsPushReceiver.this.startActivity(intent);
}
});
am.setAPIDReceiver(this, new APIDReceiver() {
#Override
public void onReceive(String apid, boolean valid){
if(valid){
Log.d("push", "Got apid: " + apid);
} else {
Log.d("push", "Application registration invalid!"+ apid);
}
}
#Override
public void onAirMailInstallRefusal() {
QuadMain.register = false;
Log.d("push", "AirMail Install Refused!");
}
});
}
}
For further clarification use this link:
Help for Push notification