If mobile access is poor, use the => GitHub version

This paper mainly records:

  • There are three ways to open third-party applications or specify activities using intEnts
  • How do I determine whether the Intent can be resolved using the above three methods
  • Determines whether the Intent can be resolved for possible omissions

Basic knowledge of

1. App entry Activity and icon

By default, a normal application will have an entry for an Activity, which is written in androidmanifest.xml like this:

<application>
    <activity android:name=".MainActivity" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>.</application>Copy the code

Only configured with a such Activity, the application will know which Activity start click, if the category of value change for Android. The intent. The category, the DEFAULT, then, the application will be on the desktop can’t see the icon, I can’t open it straight away.

How to open a third-party application or specify an Activity with an Intent

  1. Only the package name is known – there needs to be a default entry Activity
  2. Start the Activity of the specified third-party app – requires the package name and Activity name, and the Activity’sExport = "true"
  3. Implicitly launch third-party applications

1. UsePackageManager.getLaunchIntentForPackage()

String package_name="xx.xx.xx";
PackageManager packageManager = context.getPackageManager();
Intent it = packageManager.getLaunchIntentForPackage(package_name);
startActivity(it);Copy the code

This method is used when you want to start the application knowing only the package name, and the only restriction on the application is the default entry Activity.

NullPointerException is raised when there is no default entry for an Activity:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.toString(a)' on a null object referenceCopy the code

Look again at getLaunchIntentForPackage () method:

/**
     * Returns a "good" intent to launch a front-door activity in a package.
     * This is used, for example, to implement an "open" button when browsing
     * through packages.  The current implementation looks first for a main
     * activity in the category {@link Intent#CATEGORY_INFO}, and next for a
     * main activity in the category {@link Intent#CATEGORY_LAUNCHER}. Returns
     * <code>null</code> if neither are found.
     *
     * @param packageName The name of the package to inspect.
     *
     * @return A fully-qualified {@link Intent} that can be used to launch the
     * main activity in the package. Returns <code>null</code> if the package
     * does not contain such an activity, or if <em>packageName</em> is not
     * recognized.
     */
    public abstract Intent getLaunchIntentForPackage(String packageName);Copy the code

Therefore, use this method to determine whether the Intent is null.

String package_name = "xx.xx.xx";
PackageManager packageManager = getPackageManager();
Intent it = packageManager.getLaunchIntentForPackage(package_name);
if(it ! =null){
    startActivity(it);
}else{
    // There is no default entry for Activity
}Copy the code

2. UseIntent.setComponent()

String package_name = "xx.xx.xx";
String activity_path = "xx.xx.xx.ab.xxActivity";
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);/ / is optional
ComponentName comp = new ComponentName(package_name,activity_path);
intent.setComponent(comp);
startActivity(intent);Copy the code

This method can start an application-specific Activity, not limited to the default entry Activity. However, this method requires many conditions, as follows:

  1. Know the package name of the App and the full path of the Activity and its name
  2. Attribute in androidmanifest.xml of the target Activity that needs to be launchedExport = "true"

How do you determine if the target Activity exists in this way?

Here are some very common usages circulating on the Internet:

String package_name = "xx.xx.xx";
String activity_path = "xx.xx.xx.ab.xxActivity";
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);/ / is optional
ComponentName cn = new ComponentName(package_name,activity_path);
intent.setComponent(cn);

if(intent.resolveActivity(getPackageManager()) ! =null) {
    startActivity(intent);
} else {
    // The specified Activity cannot be found
}Copy the code

Unfortunately, Intent. ResolveActivity () method cannot determine the existence of this way to start the Activity and if the Activity does not exist, will quote Java. Lang. IllegalArgumentException: Unknown Component exception, causing the program to crash.

Here’s the code for resolveActivity() and its similar method resolveActivityInfo() :

public ComponentName resolveActivity(PackageManager pm) {
    if(mComponent ! =null) {
        return mComponent;
    }

    ResolveInfo info = pm.resolveActivity(this,
        PackageManager.MATCH_DEFAULT_ONLY);
    if(info ! =null) {
        return new ComponentName(
            info.activityInfo.applicationInfo.packageName,
            info.activityInfo.name);
    }

    return null;
}

public ActivityInfo resolveActivityInfo(PackageManager pm, int flags) {
    ActivityInfo ai = null;
    if(mComponent ! =null) {
        try {
            ai = pm.getActivityInfo(mComponent, flags);
        } catch (PackageManager.NameNotFoundException e) {
            // ignore}}else {
        ResolveInfo info = pm.resolveActivity(this,
            PackageManager.MATCH_DEFAULT_ONLY | flags);
        if(info ! =null) { ai = info.activityInfo; }}return ai;
}Copy the code

Obviously, this method is set first ComponentName, so will return the mComponent directly to us, there is no logic to determine. ResolveActivityInfo (), on the other hand, validates and returns NULL. Therefore, we choose to use Intent. ResolveActivityInfo () after the manner of determining:

String package_name = "xx.xx.xx";
String activity_path = "xx.xx.xx.ab.xxActivity";
Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);/ / is optional
ComponentName cn = new ComponentName(package_name,activity_path);
intent.setComponent(cn);

if(intent.resolveActivityInfo(getPackageManager(), PackageManager.MATCH_DEFAULT_ONLY) ! =null) {
    startActivity(intent);
} else {
    // The specified Activity cannot be found
}Copy the code

3. Implicitly start third-party applications

This mode is used to launch functional applications in the system, such as making phone calls, sending emails, previewing images, and opening a web page using the default browser.

Intent intent = new Intent();
intent.setAction(action);
intent.addCategory(category);
intent.setDataAndType("abc://www.dfg.com"."image/gif");
startActivity(intent);Copy the code
  • Condition 1: IntentFilter has at least one action and at least one Category, without Data and Type

  • Condition 2: If there is Data, Data in the parameter must comply with the Data rule

  • Condition 3: Action and Category must match the Activity of an Action and a Category (Category DEFAULT: android. Intent. The Category. The DEFAULT)

How to launch third-party apps on Android

There are many functions of implicit launch, which are not listed one by one. If necessary, you can directly search the relevant code. Let’s open a web page as an example:

Uri uri = Uri.parse("http://www.abc.xyz");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);Copy the code

In this case, there’s nothing wrong with using intent.resolveActivity () directly:

Uri uri = Uri.parse("http://www.abc.xyz");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);

if(intent.resolveActivity(getPackageManager()) ! =null) {
    startActivity(intent);
} else {
    // The required application is not installed
}Copy the code

conclusion

Can also be found by reading the PackageManager code, use the PackageManager. QueryIntentActivities () method to determine if there is a resolution specified in the system the application of Intent.

public boolean isAvailable(Context context, Intent intent) {
    PackageManager packageManager = context.getPackageManager();
    List list = packageManager.queryIntentActivities(intent,
    PackageManager.MATCH_DEFAULT_ONLY);
    return list.size() > 0;
}Copy the code

So, to sum it up:

  • Methods aPackageManager.getLaunchIntentForPackage(), directly determine whether the returned Intent is null.
  • Way 2Intent.setComponent(), the use ofIntent.resolveActivityInfo()orpackageManager.queryIntentActivities()Two ways;
  • Mode three implicit start, useIntent.resolveActivity(),Intent.resolveActivityInfo()packageManager.queryIntentActivities()All three ways are ok.

If you have any suggestions or questions, please feel free to contact me to discuss and learn together:

  • Weibo: cafeting
  • Making: likfe
  • CSDN: He calls himself Mr. Zhang