Android: REmove icon from springboard and launch this application from other application - android

How to remove application icon from springboard but I don't want to uninstall, just remove icon from springboard and this app will be launched from another application. In a simple word, I want to make another springboard like this and launch application from there not from anywhere else. Is this possible?

To remove application from springboard you can try this:
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context,LauncherActivity.class);
packageManager.setComponentEnabledSetting(componentName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);
Now to start your application from another application you can do the following steps:
1.Create an intent with action=MAIN and category=LAUNCHER
2.Get the PackageManager from the current context using context.getPackageManager
3.packageManager.queryIntentActivity(, 0) where intent has category=LAUNCHER, action=MAIN or packageManager.resolveActivity(, 0) to get the first activity with main/launcher
4.Get the ActivityInfo you're interested in
5.From the ActivityInfo, get the packageName and name
6.Finally, create another intent with with category=LAUNCHER, action=MAIN, componentName = new ComponentName(packageName, name) and setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
7.Finally, context.startActivity(newIntent)

In the AndroidMainfest.xml of your application, remove the below line for the activity that you do not want to have the launcher.
<category android:name="android.intent.category.LAUNCHER" />
and change android.intent.action.MAIN action to something that is your app specific
<action android:name="android.intent.action.MAIN" />
For example, one can change it to below to represent custom intent action:
<action android:name="com.example.action.MAIN" />
Now, you should be able to launch this application from another application using something like this:
Intent intent = new Intent("com.example.action.MAIN");
currentActivity.startActivity(intent);
More info here: http://developer.android.com/guide/components/intents-filters.html

Related

android explicit intent by name not resolving to other activity

I have 2 apps that are used in conjunction with one another. I want to create a button that launches app A from app B so I am creating an intent like so in app B:
Intent intent = new Intent("com.org.orgmobile.android.action.ACTION_CUSTOM");
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setData(Uri.parse(url));
startActivity(intent);
where url is https://org.org.com/mobile/Support/action/org/ActionEnumValue/?a=123
the intent filter I have declared in app A's manifest is like so:
<intent-filter>
<action android:name="com.org.orgmobile.android.action.ACTION_CUSTOM"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:scheme="https"/>
<data android:host="org.org.com"/>
<data android:pathPrefix="/mobile/Support/action/${manifestplaceholderattr}.*/ActionEnumValue/*"/>
</intent-filter>
and manifestplaceholderattr is an empty string.
I am getting
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.org.orgmobile.android.action.ACTION_CUSTOM dat=https://org.org.com/... flg=0x20000000 }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1936)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1615)
at android.app.Activity.startActivityForResult(Activity.java:4472)
at android.app.Activity.startActivityForResult(Activity.java:4430)
at android.app.Activity.startActivity(Activity.java:4791)
at android.app.Activity.startActivity(Activity.java:4759)
What am I overlooking here? I have tried using pathPattern instead of path prefix with no success.
Edit: to provide more detail, I don't just want to launch that specific activity, I want to match the specific intent associated with that activity to launch the activity. I don't want to launch the activity directly because in the case that the user's app is out of date because it won't have the desired behavior.
Best way to do this through Package manager as below.
PackageManager manager = getPackageManager();
try {
Intent intent = manager.getLaunchIntentForPackage("app B package name here");
if (intent == null)
throw new PackageManager.NameNotFoundException();
intent.addCategory(Intent.CATEGORY_LAUNCHER);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
}
Package manager checks if app with the given package name is installed, if exists it launches the app else it throws NameNotFoundException
You need to use pathPattern instead of pathPrefix. Also you should use .* instead of * at the end of the pattern:
<data android:pathPattern="/mobile/Support/action/${manifestplaceholderattr}.*/ActionEnumValue/.*"/>
This may also not work. If I recall, pathPattern isn't a real regular expression and you may not be able to match the URL like this. Try it and see. If this doesn't work, you'll probably need to rely on just the first part of the path. Let me know how it goes.
See the documentation on path, pathPattern and pathPrefix.
You need to use code as below to launch other App using custom action.
Intent intent = new Intent();
intent.setAction("com.org.orgmobile.android.action.ACTION_CUSTOM");
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.setData(Uri.parse(url));
startActivity(intent);
Also make sure both of your application is installed. Also it is better to have check as below to make sure application exists on the phone to handle such Intent.
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
boolean isIntentSafe = activities.size() > 0;

How to set default app launcher programmatically?

I am creating a launcher (kiosk) app that will be downloadable through google. When first installing this application the user has the ability of choosing which launcher (mine or the stock) will be the default. I am trying to bring this up manually if the user does not make my application the default launcher. I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up, otherwise the dialog will continue to appear periodically with a friendly message. This is what I have attempted so far.
I created a method to check for if my application is the default
/**
* method checks to see if app is currently set as default launcher
* #return boolean true means currently set as default, otherwise false
*/
private boolean isMyAppLauncherDefault() {
final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
List<IntentFilter> filters = new ArrayList<IntentFilter>();
filters.add(filter);
final String myPackageName = getPackageName();
List<ComponentName> activities = new ArrayList<ComponentName>();
final PackageManager packageManager = (PackageManager) getPackageManager();
packageManager.getPreferredActivities(filters, activities, null);
for (ComponentName activity : activities) {
if (myPackageName.equals(activity.getPackageName())) {
return true;
}
}
return false;
}
Then I make the attempt of launching the chooser
/**
* method starts an intent that will bring up a prompt for the user
* to select their default launcher. It comes up each time it is
* detected that our app is not the default launcher
*/
private void launchAppChooser() {
Log.d(TAG, "launchAppChooser()");
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
When I do this I am not receiving the choice between my app and the stock launcher. I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.
I can create a custom dialog for this instead of launching chooser but I need to know how to set the default app launcher programmatically. Thanks in advance!
This is actually possible with a little workaround:
Create an empty Activity that acts as a launcher called FakeLauncherActivity. Add it to your manifest as a disabled component:
<activity
android:name="com.path.to.your.FakeLauncherActivity"
android:enabled="false">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Check whether your desired launcher activity is the default one (with the isMyAppLauncherDefault() from your question).
If not, offer the user to choose the preferred launcher activity like this:
public static void resetPreferredLauncherAndOpenChooser(Context context) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, com.path.to.your.FakeLauncherActivity.class);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
selector.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(selector);
packageManager.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
}
This method temporarily enables FakeLauncherActivity, which leads to a change in the set of available launcher activities, which forces Android to forget its default launcher. You will see something like...
521-735/system_process I/PackageManager﹕ Result set changed, dropping preferred activity for Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 } type null
... in your log.
The method then simply opens a launcher intent where you can see all installed launchers and the buttons "Always" / "Just once".
Finally, the method disables FakeLauncherActivity again so that it doesn't display in the list.
You could repeat that as often as you want and only let the user proceed if your desired launcher activity is set as default.
The isMyAppLauncherDefault() function in the question doesn't always work for some reason.
This code might be better for determining what is the default package for the HOME screen.
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
ResolveInfo resolveInfo = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
String currentHomePackage = resolveInfo.activityInfo.packageName;
I want the user to be forced into selecting ALWAYS instead of JUST ONCE when that dialog comes up
That is not possible, except perhaps on rooted devices, barring some security flaw in Android.
When I do this I am not receiving the choice between my app and the stock launcher
Correct. If a default has already been chosen, this will simply launch the default.
I tried using startActivity(Intent.createChooser(intent, "Please set launcher settings to ALWAYS")); and I get the choices between my app and the stock launcher, however, I don't get the options ALWAYS or JUST ONCE.
Correct. createChooser() forces a choice, but does not allow setting a default.
Android Q (API 29) has RoleManager. Let's say your app is a Launcher.
[AndroidManifest.xml]
<activity
... />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
private val startForResult = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
// Perhaps log the result here.
}
}
private fun showLauncherSelection() {
val roleManager = requireActivity().getSystemService(Context.ROLE_SERVICE)
as RoleManager
if (roleManager.isRoleAvailable(RoleManager.ROLE_HOME) &&
!roleManager.isRoleHeld(RoleManager.ROLE_HOME)
) {
val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_HOME)
startForResult.launch(intent)
}
}
When you call showLauncherSelection(), you should see a dialog similar to the following.
There are other roles, such as ROLE_BROWSER, ROLE_DIALER, ROLE_SMS, and such.
If you are implementing Google EMM solution (Dedicated Device):
https://developer.android.com/work/dpc/dedicated-devices/cookbook
// Create an intent filter to specify the Home category.
IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
filter.addCategory(Intent.CATEGORY_HOME);
filter.addCategory(Intent.CATEGORY_DEFAULT);
// Set the activity as the preferred option for the device.
ComponentName activity = new ComponentName(context, KioskModeActivity.class);
DevicePolicyManager dpm =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
dpm.addPersistentPreferredActivity(adminName, filter, activity);

Remove Activity as Default Launcher

I set my activity as a default launcher to intercept home button clicks like so:
<activity
android:name=".ExampleActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
When my activity, ExampleActivity is launched, if i click the home key, I get prompted to choose. If I select make this my default and chose my activity, I am stuck In my activity as desired.
The problem is, when I leave the activity, I try to remove my activity from the default launcher, but am unsuccessful.
I have tried:
ComponentName componentName = new ComponentName(
"com.example.exampleactivity",
"com.example.exampleactivity.class");
pm.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, PackageManager.DONT_KILL_APP);
And:
PackageManager pm = getActivity().getPackageManager();
ComponentName name = new ComponentName(this, "com.example.exampleactivity.class");
pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);
But my designation for the home is never removed.
Does anyone have a working way to fix the above?
I only wan't the home button to be default for a specific activity, not my entire application. When I leave the activity, it should be removed and restored to default.
if it's your app that you're clearing its defaults , you can simply call :
getPackageManager().clearPackagePreferredActivities(getPackageName());
then , in order to show the dialog of choosing which launcher to use , use:
final Intent intent=new Intent();
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
startActivity(intent);
This solution is a clever way of doing it:
Clearing and setting the default home application
The code in onResume() basically goes like this:
ComponentName componentName = new ComponentName(MyActivity.this, FakeHome.class);
if (!isMyLauncherDefault()) {
Log.e(TAG, "MyActivity is not default home activity!");
// toggle fake activity
PackageManager pm = getPackageManager();
int flag = ((pm.getComponentEnabledSetting(componentName) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED
: PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
pm.setComponentEnabledSetting(componentName, flag, PackageManager.DONT_KILL_APP);
// start home activity to enable chooser
Intent selector = new Intent(Intent.ACTION_MAIN);
selector.addCategory(Intent.CATEGORY_HOME);
startActivity(selector);
}
and the method isMyLauncherDefault() is taken from here:
How to check if my application is the default launcher
You cannot override the behavior of the home key to suit your application; this is a design decision by Google, to ensure the user can always return to a static location. There may be some ways around this (if they still exist) but they are unintended bugs which an application should not rely on.
The short answer: you can have any key except the home key.
Have a look at the android.permission.SET_PREFERRED_APPLICATIONS permission. Also this method http://developer.android.com/reference/android/content/pm/PackageManager.html#clearPackagePreferredActivities(java.lang.String)

Launch Main Activity with Implicit Intent in Service

I have an implicit intent in a service that sends information to my main activity, as well as to another class. I also now want that intent to launch my main activity. I've looked at the myriad posts related to this, and tried lots of different things--addCategory, setAction(MAIN; the activity's name; you name it, I've tried it...), category.DEFAULT in the manifest, and several other things that either resulted in ActivityNotFoundExceptions (most commonly) or behavior that was otherwise undesirable.
Here's where the intent is set up and the relevant part of the manifest. The receiver for the intent is registered in the main activity.
final String NEW_DOSES = "changed to protect the innocent";
Intent bluetoothBroadcast = new Intent();
several putExtra lines here
bluetoothBroadcast.setAction(NEW_DOSES);
sendBroadcast(bluetoothBroadcast);
<activity
android:name=".AsthmaAppActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Is it possible to get this intent to launch my main activity with relatively minor changes? Thanks in advance.
Yes it is possible but no with sendBroadcast(bluetoothBroadcast); sendBroadcast does not launch an activity. You must use startActivity to achieve this. For example here is what a launcher application will do in order to launch an application:
public static void LaunchApplication(Context cx, String packagename) {
PackageManager pm = cx.getPackageManager();
Intent i = pm.getLaunchIntentForPackage(ai.packageName);
if (i != null) cx.startActivity(i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
You can easily adjust the extras and the data needed in order to launch the activity. For example if your activity is named myActivity then you can go like this:
Intent i = new Intent(cx, myActivity.class);
//Put the extras and the data you want here...
//If you are launching the activity from a receiver component you must use
//i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
cx.startActivity(i);
Hope this helps...

Android how to programmatically hide launcher icon

my app is designed to only need to be run once. As such I want to hide the icon from the launcher after the first run, but without uninstalling the app.
I have seen similar applications - they can remove their own icons from the launcher app list. How can I achieve the same results? Thank you.
PackageManager p = getPackageManager();
p.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
Note that the icon may not be gone until the next reboot.
Hide app's icon using below code
PackageManager pkg=this.getPackageManager();
pkg.setComponentEnabledSetting(new ComponentName(this,SplashActivity.class),PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
// activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
Here is how to bring back the app's icon
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this,SplashActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
With Android Q (API 29) Google changed the Launcher icon visibility behaviour. Even if you disable your Launcher Activity or completely remove the
android.intent.category.LAUNCHER <intent-filter> from all your Activities, the app will appear in the launcher and open the Android OS app settings, with the exception of:
Packages that don't declare any permissions in their respective manifest files
System apps
Apps that don't contain any components inside their
respective manifest's tag
You can have an app without a launcher by NOT including an intent filter with MAIN and LAUNCHER in the declaration of the Activity in the AndroidManifest - the question then becomes how to do the first kick off.. Widget maybe ?
Hide app icon using this code:
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class); // activity which is first time open in manifiest file which is declare as <category android:name="android.intent.category.LAUNCHER" />
p.setComponentEnabledSetting(componentName,PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
and bring it back, with this:
PackageManager p = getPackageManager();
ComponentName componentName = new ComponentName(this, com.apps.MainActivity.class);
p.setComponentEnabledSetting(componentName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
NOTE: This will not work for Android 10

Categories

Resources