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
Related
Let me start by saying I know this is a very similar question to others that have been answered, but they aren't helping me to solve my problem.
The question Resume application and stack from notification is exactly the same problem as mine, but the selected answer doesn't work for me and I don't quite understand why it even would?
Simply enough, I want to be able to resume my app from a notification click and regardless of what activity was open I want it to return to the last activity open. So if I'm in activity F, then press the home button and a couple minutes later I press the notification.. I want to return back to activity F. I cannot go back to the MainActivity as the user is sometimes forced to stay on a certain activity.
This answer - https://stackoverflow.com/a/5502950/4662037 is shown below:
final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
It seems to be correct as so many people have accepted it but what exactly is "YourActivity" in this case?.. I don't want to set it to a specific activity!
EDIT: Updated code for notification
private void setForegroundService(){
CharSequence text = getString(R.string.app_name);
PackageManager pm = getPackageManager();
Intent notificationIntent = pm.getLaunchIntentForPackage("com.example.xxxx.xxxxx");
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, 0);
// Create the notification
Notification notification = new NotificationCompat.Builder(this)
.setContentText(text)
.setSmallIcon(R.drawable.nurse_call_app_icon)
.setContentTitle(text)
.setContentIntent(contentIntent).build();
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;
// Start the actual service
startForeground(Integer.MAX_VALUE, notification);
}
Manifest code:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.xxxxx.xxxxxx"
android:versionCode="1"
android:versionName="0.0.1" >
<uses-sdk android:minSdkVersion="14" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.Camera" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />
<application
android:name=".xxxxxxx"
android:allowBackup="true"
android:icon="#drawable/xxxxxx"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service android:name=".xxxxxxService" />
<activity
android:name=".activities.LoginActivity"
android:label="#string/app_name"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.MainActivity"
android:label="#string/app_name"
android:launchMode="singleTop"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".activities.AlarmActivity"
android:icon="#drawable/ic_action_alarms"
android:label="#string/alarm_details"
android:parentActivityName=".activities.MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.SettingsActivity"
android:icon="#drawable/ic_action_settings"
android:label="#string/settings"
android:parentActivityName=".activities.MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.MessageListActivity"
android:icon="#drawable/ic_action_email"
android:label="#string/title_activity_text"
android:launchMode="singleTask"
android:parentActivityName=".activities.MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.MessageActivity"
android:icon="#drawable/ic_action_read"
android:label="#string/message"
android:parentActivityName=".activities.MessageListActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MessageListActivity" />
</activity>
<activity
android:name=".activities.BreakActivity"
android:icon="#drawable/ic_action_person"
android:label="#string/title_activity_break"
android:screenOrientation="portrait" >
</activity>
<activity
android:name=".activities.ContactsActivity"
android:icon="#drawable/ic_action_group"
android:label="#string/title_activity_contacts"
android:parentActivityName=".activities.MainActivity"
android:screenOrientation="portrait" >
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activities.MainActivity" />
</activity>
<activity
android:name=".activities.CallActivity"
android:icon="#drawable/ic_action_call"
android:label="#string/title_activity_call"
android:screenOrientation="portrait" >
</activity>
<receiver
android:name=".BootUpReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<receiver
android:name=".PhoneCallReceiver"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
</application>
So a quick overview of what it does:
It starts with the LoginActivity, after you login it will destroy that and the MainActivity will then become the root of everything. You can navigate up and down between stacks but never below the MainActivity unless you call a logout.
Look at my question here.
This is how you are supposed to do it:
Intent notificationIntent = new Intent(getApplicationContext(), MainActivity.class);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, 0);
Notification notification = new Notification(R.drawable.floating2, "Click to start launcher",System.currentTimeMillis());
notification.setLatestEventInfo(getApplicationContext(), "Start launcher" , "Click to start launcher", pendingIntent);
notification.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_ONGOING_EVENT;
NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(ID_NOTIFICATION,notification);
YourActivity is the root activity. That's the one that is defined with ACTION=MAIN and CATEGORY=DEFAULT in your manifest.
You will also need to set FLAG_ACTIVITY_NEW_TASK as well:
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
This doesn't actually start any Activity (if your app is already running). It just brings the task containing your app to the foreground in the same state it was in when it went to the background, which is what you want.
UPDATE:
Since you seem to be having problems with this, please try this alternative suggestion:
PackageManager pm = getPackageManager();
// NOTE: replace com.example.xxx.xxx with the package name from your manifest!
Intent notificationIntent = pm.getLaunchIntentForPackage("com.example.xxx.xxx");
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0,
notificationIntent, 0);
I resolve this issue by saving top activity intent in onResume method of BaseActivity like below:
Intent currentActivityIntent = new Intent(this, getClass());
currentActivityIntent.addFlags(FLAG_ACTIVITY_NEW_TASK);
currentActivityIntent.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
App.setCurrentActivityIntent(currentActivityIntent);
I get top activity intent after clicking on push.
All you need is to get intent of last top activity with the two flags
FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_SINGLE_TOP.
I am trying to start activities from a class that extends Application. I am able to do that using FLAG_NEW_ACTIVITY_TASK as flag intent that is creating the activity.
Let me illustrate a scenario that I am trying to implement.
There are two users USER1 and USER2. If USER1 presses a button(HOLD) a new activity is created on USER2's device. This launching of new activity on USER2's device is done by the class that extends Application. Then when USER1 presses a button(UNHOLD) I want the USER2's device to bring up the previous activity. I am able to bring up the previous activity but it is being recreated because of the FLAG_NEW_ACTIVITY_TASK flag, I want that activity to be resumed instead of being recreated.
I am stuck here, I did search on google but could not understand what should I do. Please Help.
Manifest:
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:name=".MyApplication" >
<service android:name=".PortSipService"></service>
<service android:name=".Ringback"></service>
<service android:name=".LocationService"></service>
<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>
<activity android:name=".SaveContacts" android:label="#string/app_name"> </activity>
<activity android:name=".IncomingCall" android:label="#string/app_name"> </activity>
<activity android:name=".ContactActivity" android:label="#string/app_name"></activity>
<activity android:name=".CallConnected" android:label="#string/app_name"></activity>
<activity android:name=".OutgoingCall" android:label="#string/app_name"></activity>
<activity android:name=".MusicPlayer" android:label="#string/app_name"></activity>
</application>
This is when on hold,
Intent music = new Intent(getApplicationContext(),MusicPlayer.class); music.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(music);
This is when unhold pressed,
Intent connect = new Intent(getApplicationContext(),CallConnected.class);
connect.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(connect);
I do not want this callconnected activity to be recreated, But it is because of the intent flag.
You may try use Activity instead Context like this:
Intent music = new Intent(MainActivity.this,MusicPlayer.class);
music.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainActivity.this.startActivity(music);
I have a live wallpaper which displays an image. I change that image in an activity. I then need to notify the live wallpaper, so it knows to reload the resources.
Intents seemed like the perfect, simple, solution:
Intent intent = new Intent(MyActivity.this, MyWallpaperService.class);
startService(intent);
I and in MyWallpaperService
#Override
public int onStartCommand (Intent intent, int flags, int startId) {...}
I also need to know, in another service, when the user taps the screen. I use the exact same mechanism of sending and receiving the intent.
Everything is working perfectly on Android 4.0+ devices and emulators.
But I tested on Android 2.2 and 2.3.3 emulator and get the following error:
java.lang.SecurityException: Not allowed to start service Intent { cmp=com.domain.name/.liveWallpaper.MyWallpaperService } without permission android.permission.BIND_WALLPAPER
My manifest contains the correct android:permission inside the service tag:
<service
android:name=".liveWallpaper.MyWallpaperService"
android:label="#string/app_name"
android:permission="android.permission.BIND_WALLPAPER" >
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data
android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper_data" />
</service>
Why do I get this error only on old versions(Android 2.2 and 2.3.3)? Is sending Intents to a WallpaperService not allowed or recommended? Does it have something to do with the fact that only the system can bind to a service with the BIND_WALLPAPER permission?
In the end, if intents do not work, what is an alternative, simple, solution?
try to add the permission to your Service in the manifest file , like the following :
<service android:name=".LiveWallpaper"
android:label="#string/app_name"
android:icon="#drawable/icon"
android:permission="android.permission.BIND_WALLPAPER">
Hope that Helps
java.lang.SecurityException: Not allowed to start service Intent {
cmp=com.domain.name/.liveWallpaper.MyWallpaperService } without
permission android.permission.BIND_WALLPAPER
means you probably forgot to declare the BIND_WALLPAPER permission within your AndroidManifest.xml like this:
<service
android:enabled="true"
android:name="MyWallpaperService"
android:permission="android.permission.BIND_WALLPAPER" />
Android Livewallpaper settings fail to load from 'configure...' menu
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.RrD"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<uses-feature android:name="android.software.live_wallpaper" />
<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.BIND_WALLPAPER" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
>
<service android:name=".LiveWallpaper"
android:label="#string/app_name"
android:icon="#drawable/icon"
android:permission="android.permission.BIND_WALLPAPER">
<intent-filter>
<action android:name="android.service.wallpaper.WallpaperService" />
</intent-filter>
<meta-data android:name="android.service.wallpaper"
android:resource="#xml/livewallpaper" />
</service>
<activity android:label="PAM_Prefs"
android:name=".PAM_Prefs"
android:exported="true" android:icon="#drawable/icon">
<intent-filter>
<category android:name="android.intent.category.PREFERENCE" />
</intent-filter>
</activity>
</application>
</manifest>
I still haven't found a exact explanation for why this isn't working, but I found a solution:
Creating a BroadcastReceiver that will receive my custom Intents. This means I will no longer be using startService(intent), but sendBroadcast(intent), which will not cause permission issues.
See the references for more explanations and code.
References:
https://groups.google.com/forum/#!topic/android-developers/N8TzbbKwd5o
Permission to BIND_WALLPAPER required when messaging WallpaperService from Settings Activity
In MainActivity, I call SincActivity.
This screen has a "start" button, a TextView and a ProgressBar to show the status.
The button start an AsyncTask. This AsyncTask updates the components on the screen, and also in the notification area.
The notification area can be clicked. I passed into their creation which Activity it should open. I have spent SincActivity.
When the user is on the screen SincActivity and click the button, all components are updated as expected.
When I click on the notification area, android opens a new screen SincActivity, with initial values.
It's as if somewhere, android execute: "new SincActivity";
What I need is to be shown always the same screen.. the same instance. Almost like a singleton.
Is this possible?
UPDATE
AndroidManifest.xml
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="br.com.rokko.gabinetemobile.MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="#style/FullscreenTheme" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="br.com.rokko.gabinetemobile.ModeloActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="#string/title_activity_modelo"
android:theme="#style/FullscreenTheme" >
</activity>
<activity
android:name="br.com.rokko.gabinetemobile.SincActivity"
android:label="#string/sincronizacao" ><!-- android:launchMode="singleInstance" don't work -->
</activity>
</application>
Try adding android:launchMode="singleInstance" to the <activity> tag for this Activity in your AndroidManifest.xml file.
If you just want the notification to bring your task to the foreground, without creating any new instances of activities, you need to use a "launch Intent" in your notification. Something like this:
Intent intent = new Intent(this, MainActivity.class);
// Set the action and category so it appears that the app is being launched
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
use pendingIntent when you create your notification.
For more information, see Android application current activity bring to front issue
I've been looking ALL DAY to no avail..I know there are several questions on this but I haven't been able to find one that works properly for me.
Basically, I have an activity (MainActivity), with a function to add a shortcut to the home screen. When I click the shortcut, I want it to open a different activity (NewActivity). The hold up here seems to be that it doesn't work right when I try to launch a different activity than the one from which the shortcut was made.
The shortcut is successfully made, but when I click it I get an "App isn't installed" toast message from the Android system.
Here's the code for adding the shortcut:
Intent shortcutIntent = new Intent();
shortcutIntent.setClassName("com.enceladus.myApp", "com.enceladus.myApp.NewActivity");
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Intent addIntent = new Intent();
addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "Calculator");
addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource.fromContext(MainActivity.this, R.drawable.calc));
addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
MainActivity.this.sendBroadcast(addIntent);
EDIT: Here's my manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.enceladus.myApp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.enceladus.myApp.NewActivity"
android:label=""
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleInstance"
/>
</application>
NewActivity.class functions perfectly (I know because I've debugged it a lot), so that's not the problem.
Try making your manifest look like this for the NewActivity entry:
<activity android:name="com.enceladus.myApp.NewActivity"
android:label=""
android:screenOrientation="portrait"
android:theme="#android:style/Theme.Translucent.NoTitleBar"
android:launchMode="singleInstance"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
</intent-filter>
</activity>
also maybe try making the shortcut intent like this:
Intent shortcutIntent = new Intent(MainActivity.this, NewActivity.class);
shortcutIntent.setAction(Intent.ACTION_MAIN); //Not sure if you'll need this or not.
//remove the next line.
//shortcutIntent.setClassName("com.enceladus.myApp", "com.enceladus.myApp.NewActivity");
The other way that you can do this is by setting the android:exported flag to true.