i'm creating a launcher app and i would like to show the default launcher chooser manually.
I already found and tried this but this is not perfect, since i cannot select ALWAYS immediately. After choosing the launcher i need to press the home button to be able to select ALWAYS.
This is my code:
public static void resetPreferredLauncherAndOpenChooser(Context context) {
PackageManager packageManager = context.getPackageManager();
ComponentName componentName = new ComponentName(context, DefaultLauncherHelperActivity.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);
}
and here the manifest:
<activity
android:name=".activities.MainActivity"
android:launchMode="singleTask">
<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>
<activity
android:name=".activities.DefaultLauncherHelperActivity"
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>
This is what i get (left) vs. what i'm trying to achieve (right)
There has to be a way since Microsoft's launcher and the poco launcher are able to do this but i couldn't find a solution and unfortunately there is no open source launcher with the same functionality. Can anyone help me with this?
There is no straight forward API available for this. However, calling below code before resetting preferred launcher will result in chooser dialog as per right side image.
Use it cautiously as calling this will actually resets user home app preference and effect can be seen outside of your home app as well.
try {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MAIN);
intentFilter.addCategory(CATEGORY_HOME);
intentFilter.addCategory(CATEGORY_DEFAULT);
Intent intent1 = new Intent(Intent.ACTION_MAIN);
intent1.addCategory(CATEGORY_HOME);
intent1.setComponent(null);
Class<?> clazz = Class.forName("android.app.AppGlobals");
Class.forName("android.content.pm.IPackageManager")
.getMethod("setLastChosenActivity", new Class[] { Intent.class, String.class, int.class, IntentFilter.class, int.class, ComponentName.class })
.invoke(clazz.getMethod("getPackageManager", new Class[0]).invoke(clazz, null),
new Object[] { intent1, intent1.resolveTypeIfNeeded(context.getContentResolver()), Integer.valueOf(65536), intentFilter, Integer.valueOf(1081344), intent1.getComponent() });
} catch (Exception ignore) {
}
i've tried to sending data between App1 to App2 via Intent in Android
i used this code but i couldn't resolve my problem.
App1 MainActivity :
Intent i2 = new Intent("com.appstore.MainActivity");
i2.setPackage("com.appstore");//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
App2 MainActivity :
Bundle data = getIntent().getExtras;
if(data!=null){
String myString = b.getString("Id");
}
Manfiest App2 MainActivity:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
Final code:
App 1 :
Intent intent = new Intent();
intent.setClassName("com.appstore", "com.appstore.MyBroadcastReceiver");
intent.setAction("com.appstore.MyBroadcastReceiver");
intent.putExtra("KeyName","code1id");
sendBroadcast(intent);
App 2:
Reciver:
public class MyBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Data Received from External App", Toast.LENGTH_SHORT).show();
}
}
Manifest :
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="first_app_packagename" />
</intent-filter>
</receiver>
MainActivity :
MyBroadcastReceiver mReceiver = new MyBroadcastReceiver();
registerReceiver(mReceiver,
new IntentFilter("first_app_packagename"));
My requirement was to send the "user id" from App1 to App2 and get "username" back to App1.
I needed to launch my app directly without any chooser. I was able to achieve this using implicit intent and startActivityForResult.
App1 > MainActivity.java
private void launchOtherApp() {
Intent sendIntent = new Intent();
//Need to register your intent filter in App2 in manifest file with same action.
sendIntent.setAction("com.example.sender.login"); // <packagename.login>
Bundle bundle = new Bundle();
bundle.putString("user_id", "1111");
sendIntent.putExtra("data", bundle);
sendIntent.setType("text/plain");
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(sendIntent, REQUEST_CODE);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
Bundle bundle = data.getBundleExtra("data");
String username = bundle.getString("user_name");
result.success(username);
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
I had two activity in App2 ie. MainActivity and LoginActivity.
App2 > AndroidManifest.xml
<activity android:name=".LoginActivity">
<intent-filter>
<!--The action has to be same as App1-->
<action android:name="com.example.sender.login" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
Sorry for this I had a little mix up with Java and Kotlin. My second app was in Kotlin, not that it will effect in any way.
App2 > LoginActivity.java
override fun onResume() {
super.onResume()
var userId = "No data received"
val intent = intent
if (intent != null
&& intent.action != null
&& intent.action.equals("com.example.sender.login")
) {
val bundle = intent.getBundleExtra("data")
if (bundle != null) {
userId = bundle.getString("user_id")
userId = " User id is $userId"
}
}
tvMessage.text = "Data Received: $userId"
}
fun onClickBack(view: View) {
val intent = intent
val bundle = Bundle()
bundle.putString("sesion_id", "2222")
intent.putExtra("data", bundle)
setResult(Activity.RESULT_OK, intent)
finish()
}
When you do this:
Intent i2 = new Intent("com.appstore.MainActivity");
i2.setPackage("com.appstore");//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
you are calling the single-argument constructor of Intent. In this constructor, the argument is interpreted as the Intent ACTION. You then set the package name in the Intent.
When you call startActivity() with this Intent, Android will look for an Activity that contains an <intent-filter> with the specified ACTION. There are no installed applications that have an Activity defined like this in the manifest:
<activity>
<intent-filter>
<action android:name="com.appstore.MainActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
So Android will not be able to find and launch the Activity that you want.
As you want to specify explicitly the component that you want to use, instead of using the 1-argument Intent constructor, you should do this instead:
Intent i2 = new Intent();
i2.setClassName("com.appstore", "com.appstore.MainActivity");
i2.putExtra("Id", "100");
startActivity(i2);
Using setClassName() you provide the package name and the class name of the component that you want to launch.
This should work:
APP1
Intent i2 = new Intent();
i2.setComponent(new ComponentName(PACKAGE,ACTIVITY));//the destination packageName
i2.putExtra("Id", "100");
startActivity(i2);
APP2
String myString = getIntent().getStringExtra("Id");
Using Bundle.putSerializable(Key,Object); and Bundle.putParcelable(Key, Object);
the former object must implement Serializable, and the latter object must implement Parcelable.
Content providers:
Content providers are the standard interface that connects data in one process with code running in another process.
See Android Docs.
Content provider working demo here.
The idea is to manage what activity will be launched depending on already set up properties?
Now I'm using Activity A1 which decides Activity A2 or Activity A3 will be launched.
A1 extends Activity{
...
onCreate(...) {
Intent intent = new Intent();
if (launchA2){
intent = new Intent(this,A2.class);
} else {
intent = new Intent(this,A3.class);
}
startActivity(intent);
finish();
}
...
}
Is there any solution to move this logic into Application class or somewhere without A1 class?
Futhermore, there is another problem about AndroidManifest.xml file.
<activity
android:name="A1"
android:launchMode="singleTop"
android:label="#string/app_alias">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Is it possible to change this Activity programmatically?
Can anyone help with this code:
Intent localIntent = new Intent("android.intent.action.MULTI_MODE_CHANGED ");
localIntent.putExtra("MULTI_MODE", paramString);
mContext.sendBroadcast(localIntent);
I am trying to understand how to broadcast the same intent from am broadcast from shell.
mContext is set to null at the beginning but on the onCreate function, this is displayed:
mContext = this;
This is in the AndroidManifest.xml:
<receiver android:name="HiddenmenuBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE"/>
<data android:host="LTEMODE" android:scheme="android_secret_code"/>
</intent-filter>
</receiver>
Thanks,
Alex
EDIT: It works now
It does work now, i changed "Database.java" to "database.java" and just kept the normal
Intent startListItem = new Intent("com.grumbledorf.Hellotraining." + item.toUpperCase());
and
<activity
android:name=".databases"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.grumbledorf.Hellotraining.DATABASES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
So thanks guys!
You are trying to start the activity "com.grumbledorf.Hellotraining.database" and as I see the proper activity name would be "com.grumbledorf.Hellotraining.Databases".
proper stuff definition:
String[] stuff = new String[] { "Databases" };
But a full Manifest.xml would be helpful.
The Intent creation using reflection:
Intent startListItem = new Intent(this, Class.forName("com.grumbledorf.Hellotraining." + item.toUpperCase()));
have you tried
Intent startListItem = new Intent("com.grumbledorf.Hellotraining","com.grumbledorf.Hellotraining." + item.toUpperCase());
?