I'm trying to rig together a service that simply issues a notification on "boot" and then another one once the service is running. I'm using the following for my manifest:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="my.project"
android:versionCode="1"
android:versionName="1.0"
>
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17"
/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
>
<service
android:name=".Manager"
/>
<receiver
android:name=".Bootstrap"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
Unfortunately when I reboot my device, nothing displays and it seems like the service is never started.
Here is the implementation for my BroadcastReceiver subclass:
#Override
public void onReceive(Context context, Intent intent) {
Log.d("Test", "Bootstrap run!");
int notificationId = 1;
NotificationCompat.Builder startNotification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Glance")
.setContentText("Starting the Glance service.")
;
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, startNotification.build());
//
// Run the service.
//
Intent startServiceIntent = new Intent(context, Manager.class);
context.startService(startServiceIntent);
}
Any suggestions on what I might be doing wrong or missing here that's causing things not to work?
Thanks!
If you are testing this on Android 3.1, please add an activity to your application, then run your activity. Starting with Android 3.1, manifest-registered BroadcastReceivers are blocked until something manually runs one of your components, which typically means a user has launched one of your activities. See this nearly-two-year-old blog post for more details.
Related
I am trying to resume my activity from a notification, but it is recreating the activity and not resuming.
As all posts regarding this issue, mention creating a PendingIntent and setting this with the appropriate flags (as shown in code below), and adding the singleTop|singleInstance to the AndroidManifest.
Notification Code:
NotificationManager mNotifyMan = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNotifyMan.cancelAll();
Notification.Builder mNB = new Notification.Builder(this);
mNB.setOngoing(true);
Intent intent = new Intent(parentContext, main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getActivity(parentContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mNB.setContentIntent(pendingIntent);
mNB.setSmallIcon(R.drawable.ic_notify_icon);
mNB.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_noti_large));
mNB.setContentTitle(Title);
mNB.setContentText(Message);
mNB.setColor(0);
mNotifyMan.notify(777, mNB.build());
I understand one must pass an intent with the current context.
When resuming an activity via the onPause() on onResume(), it resumes and restores the last activity state, i.e. a thread counter running has incremented values.
Problem:
When resuming from the notification (i.e. clicking on the notification), the activity is recreated. I have attempted to resolve this by
when onPause() is executed, sending the current activity state via base class to the notification, thus recreating the notification with the current state.
Here is my AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cynetstudios.wifimanager">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:name="android.hardware.wifi" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:launchMode="singleInstance">
<activity android:name="com.cynetstudios.frequencyselector.main" android:configChanges="orientation|screenSize|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.cynetstudios.frequencyselector.serviceWifiFreqManager" android:exported="false"/>
</application>
</manifest>
I might be missing something trivial, any advice?
You can set your Activity's launchMode SingleTask, SingleTop or SingleInstance depending on how you want your activity to act.
Later you can handle your activity's onNewIntent method if your activity is open when user clicks your active notification.
Also you need to define activity's launchMode in that atcitvity's part. I edited your xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.cynetstudios.wifimanager">
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:name="android.hardware.wifi" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name="com.cynetstudios.frequencyselector.main"
android:configChanges="orientation|screenSize|keyboardHidden"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name="com.cynetstudios.frequencyselector.serviceWifiFreqManager" android:exported="false"/>
</application>
</manifest>
I hope this'll help you.
launchMode should be used in Activity section (not application)
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClass(this, main.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
startActivity(intent);
You can try this Intent. Such an intent is used by system app launcher, which will just show(no recreate) your activity if it is not killed.
Try
Intent.FLAG_ACTIVITY_CLEAR_TOP
with
Intent.FLAG_ACTIVITY_NEW_TASK
Set them as flags for the intent
Try this it may help you:
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
and as #Alexander says put android:launchMode="singleTop" into activity tag
I have researching for hour and hour and found many similar question but have no a working solution for my question.
I'm understand if I close the app by force close that is normal that I not receive data from gcm. But I was unable to receive the notification with gcm until I start the app. So the application is running either foreground or background then I only be able to receive the data from gcm but when I close the app by sliding away it (which is not done by force close) the notification didn't show up which mean gcm wasn't receive any data at all. . So it mean I need to stay active but if I do so then there is no point for using gcm anymore which design for pushing notification.
Here is my manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.khooteckwei.google" >
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcmtesting.google.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcmtesting.google.permission.C2D_MESSAGE" />
<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>
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.example.gcmtesting.google" />
</intent-filter>
</receiver>
<service android:name=".GcmIntentService" />
</application>
</manifest>
here is the wakefulBroadcastReceiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
The notification working fine when the app is active so I didn't include the function that use to display notification.Is there any problem with this 2 pages?
I think your problem is in your GcmBroadcastReceiver receiver, you can look at this link , I think it's will help you with GCM http://www.intertech.com/Blog/push-notifications-tutorial-for-android-using-google-cloud-messaging-gcm/
I think notifications doesn't work because your receiver doesn't check do your app running or not , if it is you need to handle notification or if not show android notification
I am implementing GCM for push notifications using GcmReceiver and GcmListenerService. When the app is running in the foreground or background, I receive the notifications just fine.
My problem is when I swipe the app away from the "recent tasks" list, I can't receive GCM messages anymore (I am on a Xiaomi Mi3). I understand that if you force close an app, you will not receive push notifications anymore. However, swiping it away from the "recent tasks" should still allow the app to receive push notifications.
I have tested this with WeChat and Facebook Messenger, and I do still receive notifications when I swipe the app away (but not if I force close it from Settings).
What am I doing wrong here?
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.considerdigital.p1mobileapp" >
<permission android:name="com.considerdigital.p1mobileapp.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.considerdigital.p1mobileapp.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.google.android.c2dm.permission.SEND" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".App"
android:allowBackup="true"
android:icon="#drawable/p1_app_icon"
android:label="#string/app_name"
android:theme="#style/Theme.P1mobileapp" >
<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="com.considerdigital.p1mobileapp" />
</intent-filter>
</receiver>
<service
android:name=".ListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
GcmListenerService:
public class ListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
public static final String FOREGROUND_NOTIFICATION = "FOREGROUND_NOTIFICATION";
private NotificationManager mNotificationManager;
#Override
public void onMessageReceived(String from, Bundle data) {
// Send notification only if app is in background
if (!P1GlobalVariables.getSharedInstance().isAppActive) {
System.out.println("App is inactive");
sendNotification(data);
} else {
System.out.println("App is active");
sendForegroundNotification(data);
}
Log.i(TAG, "Received: " + data.toString());
}
The following is the code I'm using for starting my Application when device is turned on.
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.i("BootReceiver","intent received");
Intent myIntent = new Intent(context, ACT_Home.class);
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
}
}
and in the Manifest (as <Application> child):
<receiver android:name="host.alarmmanager.BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
The permissions inside the Manifest are the following:
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
This works fine on Android 3.2.2, but if I try the same application on Android 4.0.3 the broadcast receiver does not receive anything.
Also the first line inside the onReceive method is not execeuted.
Why this happens?
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
This you should use in android manifest
Try this, although your code seems fine! The following is working for me.
<!-- Receivers -->
<receiver android:enabled="true" android:name="host.alarmmanager.BootReceiver"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Make sure you are not restarting your phone by selecting restart option from the power menu.
Android bizarrely has 2 different permissions.
1.Reboot
2.On boot complete
So,
first power off your phone and then after few seconds power on it again!
Hope it helps! (Y)
I have an app that automatically starts a few seconds delayed after boot. BTW: This is nothing evil! The user must enable it by himself! When I now tap on the app's icon I would like to have the same instance being opened that was already started at boot. I don't want the app to restart. But this is what happens right now.
Background: I'm writing some debug info to a TextView. When the app starts at boot, it is immediately put to background with moveTaskToBack(true), because it should not cover the screen of course. The user should see the IDLE screen. So the app (and in turn this output) can only become visible when the app is opened manually.
Here is the AndroidManifest.xml:
<application android:icon="#drawable/fritzbox"
android:label="#string/app_name"
android:allowTaskReparenting="true"
android:persistent="true">
<uses-library android:name = "com.google.android.maps" />
<receiver android:name=".BootUpReceiver">
<intent-filter>
<action android:name = "android.intent.action.BOOT_COMPLETED" />
<category android:name = "android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity android:name =".WiFiOnDemandActivity"
android:label="#string/app_name"
android:allowTaskReparenting="true"
android:launchMode="singleInstance">
<intent-filter>
<action android:name = "android.intent.action.MAIN" />
<category android:name = "android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
As you can see I've already tried android:launchMode, android:allowTaskReparenting and android:persistent. The broadcast receiver that receives the BOOT_COMPLETED broadcast creates a PendingIntent that is scheduled with the AlarmManager. So the app is started 15s (START_DELAY) after boot. Here is the code:
public class BootUpReceiver extends BroadcastReceiver implements Defines
{
private AlarmManager mAlarmManager = null;
private Intent mIntent = null;
private PendingIntent mPendingIntent = null;
#Override
public void onReceive( final Context context, final Intent intent)
{
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE );
mIntent = new Intent ( context, WiFiOnDemandActivity.class );
mIntent.setAction(intent.getAction());
mIntent.addFlags ( Intent.FLAG_ACTIVITY_NEW_TASK );
mPendingIntent = PendingIntent.getActivity( context, 0, mIntent, 0);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + START_DELAY, mPendingIntent );
}
}
Strangely enough sometimes it seems to work as expected (no restart) but sometimes it doesn't!
Thanks!
Bernd
Do show your code, but this cannot be guaranteed. The system may kill your process at any time if memory is low, so you might get a new process when you start via the launcher. What makes you think you need the exact same instance?