Cómo iniciar una actividad desde otra aplicación en Android

479

Quiero iniciar un paquete instalado desde mi aplicación de Android. Supongo que es posible usando intentos, pero no encontré una manera de hacerlo. ¿Hay un enlace, dónde encontrar la información?

Bastian
fuente
2
¿Qué sucede si abro la segunda aplicación de la primera y luego hago clic directamente en el icono de la segunda aplicación, obtengo dos instancias de la aplicación, que no es deseada? ¿Cómo administrarla?
Radhey

Respuestas:

707

Si no conoce la actividad principal, puede usar el nombre del paquete para iniciar la aplicación.

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) { 
    startActivity(launchIntent);//null pointer check in case package name was not found
}
andep
fuente
55
¿Alguna razón de por qué esto no funcionaría? No pude hacerlo funcionar al menos.
Simon Forsberg
22
Comienza una nueva intención, ¿qué tal si reanudamos la aplicación que está en segundo plano?
Salil Dua
3
@andep: Esto funcionó bien para mí cuando probé entre dos aplicaciones que creé yo mismo. Una vez que sepa el nombre del paquete, ¿esto siempre funcionará, o hay alguna manera de evitar que alguien lance su aplicación (en la forma o en algún lugar)?
Leonard Feehan
2
@Leonard: Mi primera impresión es que siempre debe funcionar, porque los nombres de los paquetes son públicos para que cualquier aplicación pueda leerlos. Desde sus aplicaciones, creo que no puede determinar desde dónde se llamó, pero su aplicación puede determinar que no se puede llamar a través de la actividad principal solo a través de los servicios.
andep
1
Sí, esto puede devolver nulo. "La implementación actual busca primero una actividad principal en la categoría CATEGORY_INFO, y luego una actividad principal en la categoría CATEGORY_LAUNCHER. Devuelve nulo si no se encuentra ninguno " .
quietmint
240

Sé que esto ha sido respondido, pero así es como implementé algo similar:

Intent intent = getPackageManager().getLaunchIntentForPackage("com.package.name");
if (intent != null) {
    // We found the activity now start the activity
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
} else {
    // Bring user to the market or let them choose an app?
    intent = new Intent(Intent.ACTION_VIEW);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setData(Uri.parse("market://details?id=" + "com.package.name"));
    startActivity(intent);
}

Aún mejor, aquí está el método:

public void startNewActivity(Context context, String packageName) {
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    if (intent != null) {
        // We found the activity now start the activity
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    } else {
        // Bring user to the market or let them choose an app?
        intent = new Intent(Intent.ACTION_VIEW);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setData(Uri.parse("market://details?id=" + packageName));
        context.startActivity(intent);
    }
}

Código duplicado eliminado:

public void startNewActivity(Context context, String packageName) {
    Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    if (intent == null) {
        // Bring user to the market or let them choose an app?
        intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("market://details?id=" + packageName));
    }
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);
}
Jared Burrows
fuente
8
Estaba teniendo un problema al iniciar una intención en un perfil de Facebook o Twitter. Se estaban abriendo dentro de mi aplicación, en lugar de como una nueva actividad. Agregar FLAG_ACTIVITY_NEW_TASK solucionó eso. ¡Gracias!
Harry
44
¡No hay problema! Estaba teniendo problemas con algo muy similar
Jared Burrows
1
El método funciona para mí, pero a veces la nueva aplicación está abierta y la actividad de llamada sigue siendo el primer plano. ¿Alguna idea de cómo solucionarlo?
lgdroid57
¿Hay alguna manera de hacer esto desde la aplicación instantánea?
Mahdi
Funciona solo para versiones de lanzamiento. Si está intentando abrir la aplicación de depuración, la intención será nula.
RexSplode
152

Encontré la solución. En el archivo de manifiesto de la aplicación encontré el nombre del paquete: com.package.address y el nombre de la actividad principal que quiero iniciar: MainActivity El siguiente código inicia esta aplicación:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);
Bastian
fuente
8
obtuve la excepción 'dosis que declaras actividad en tu Manifiesto.xml'
itzhar
De esta manera, devuelve una excepción que dice que necesito declarar la actividad en mi manifiesto ... ¡pero es una aplicación externa!
JJ Ab
¿Cómo ejecutarlo en segundo plano? Significa que las aplicaciones llamadas en segundo lugar no se muestran en la pantalla, pero ejecutan su método onCreated ().
Dr.jacky
Recibo este error cuando intento desde la aplicación instantánea: no se permite iniciar la actividad Intención
Mahdi
@Bastian, ¿cómo cerrar la aplicación actual desde donde llamamos la intención de abrir otra aplicación?
Arnold Brown el
18
// in onCreate method
String appName = "Gmail";
String packageName = "com.google.android.gm";
openApp(context, appName, packageName);

public static void openApp(Context context, String appName, String packageName) {
    if (isAppInstalled(context, packageName))
        if (isAppEnabled(context, packageName))
            context.startActivity(context.getPackageManager().getLaunchIntentForPackage(packageName));
        else Toast.makeText(context, appName + " app is not enabled.", Toast.LENGTH_SHORT).show();
    else Toast.makeText(context, appName + " app is not installed.", Toast.LENGTH_SHORT).show();
}

private static boolean isAppInstalled(Context context, String packageName) {
    PackageManager pm = context.getPackageManager();
    try {
        pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
        return true;
    } catch (PackageManager.NameNotFoundException ignored) {
    }
    return false;
}

private static boolean isAppEnabled(Context context, String packageName) {
    boolean appStatus = false;
    try {
        ApplicationInfo ai = context.getPackageManager().getApplicationInfo(packageName, 0);
        if (ai != null) {
            appStatus = ai.enabled;
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }
    return appStatus;
}
Ahamadullah Saikat
fuente
17

Aquí está mi ejemplo de cómo iniciar el escáner de código de barras / QR desde mi aplicación si alguien lo encuentra útil

Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.setPackage("com.google.zxing.client.android");

try 
{
    startActivityForResult(intent, SCAN_REQUEST_CODE);
} 
catch (ActivityNotFoundException e) 
{
    //implement prompt dialog asking user to download the package
    AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this);
    downloadDialog.setTitle(stringTitle);
    downloadDialog.setMessage(stringMessage);
    downloadDialog.setPositiveButton("yes",
            new DialogInterface.OnClickListener() 
            {
                public void onClick(DialogInterface dialogInterface, int i) 
                {
                    Uri uri = Uri.parse("market://search?q=pname:com.google.zxing.client.android");
                    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
                    try
                    {
                        myActivity.this.startActivity(intent);
                    }
                    catch (ActivityNotFoundException e)
                    {
                        Dialogs.this.showAlert("ERROR", "Google Play Market not found!");
                    }
                }
            });
    downloadDialog.setNegativeButton("no",
            new DialogInterface.OnClickListener() 
            {
                public void onClick(DialogInterface dialog, int i) 
                {
                    dialog.dismiss();
                }
            });
    downloadDialog.show();
}
Tine M.
fuente
13

Editar dependiendo del comentario

En algunas versiones, como se sugiere en los comentarios, la excepción lanzada puede ser diferente.

Por lo tanto, la solución a continuación se modifica ligeramente

Intent launchIntent = null;
try{
   launchIntent = getPackageManager().getLaunchIntentForPackage("applicationId");
} catch (Exception ignored) {}

if(launchIntent == null){
    startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://play.google.com/store/apps/details?id=" + "applicationId")));
} else {
    startActivity(launchIntent);
}

Respuesta original

Aunque se respondió bien, hay una implementación bastante simple que maneja si la aplicación no está instalada. Lo hago asi

try{
    startActivity(getPackageManager().getLaunchIntentForPackage("applicationId"));
} catch (PackageManager.NameNotFoundException e) {
    startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://play.google.com/store/apps/details?id=" + "applicationId")));
}

Reemplace "applicationId" con el paquete que desea abrir, como com.google.maps, etc.

mayank1513
fuente
El PackageManager.getLaunchIntentForPackage(...)método devuelve nulo si no se reconoce el nombre del paquete. No tira PackageManager.NameNotFoundException. Ver aquí .
Adil Hussain el
Acabo de probar startActivity(null)un emulador de Android 10 y arroja un NullPointerExceptiony no un PackageManager.NameNotFoundException.
Adil Hussain
En mi nota 7 funciona exactamente de la manera prevista.
mayank1513
¿Cuál es el comportamiento previsto del startActivity(Intent intent)método cuando se le da un valor nulo Intenty qué te hace decir eso? La documentación de los desarrolladores de Android solo indica que arrojará un ActivityNotFoundException.
Adil Hussain
Hola @Adil ¿Me podría ayudar con esta pregunta - stackoverflow.com/q/59615815/9640177
mayank1513
7
// check for the app if it exist in the phone it will lunch it otherwise, it will search for the app in google play app in the phone and to avoid any crash, if no google play app installed in the phone, it will search for the app in the google play store using the browser : 

 public void onLunchAnotherApp() {

        final String appPackageName = getApplicationContext().getPackageName();

        Intent intent = getPackageManager().getLaunchIntentForPackage(appPackageName);
        if (intent != null) {

            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

        } else {

            onGoToAnotherInAppStore(intent, appPackageName);

        }

    }

    public void onGoToAnotherInAppStore(Intent intent, String appPackageName) {

        try {

            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("market://details?id=" + appPackageName));
            startActivity(intent);

        } catch (android.content.ActivityNotFoundException anfe) {

            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("http://play.google.com/store/apps/details?id=" + appPackageName));
            startActivity(intent);

        }

    }
Ingeniero Karima
fuente
¿hay un límite de caracteres para el método uri.parse?
API
7

Si desea abrir una actividad específica de otra aplicación, podemos usar esto.

Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
final ComponentName cn = new ComponentName("com.android.settings", "com.android.settings.fuelgauge.PowerUsageSummary");
intent.setComponent(cn);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try 
{
    startActivity(intent)
}catch(ActivityNotFoundException e){
    Toast.makeText(context,"Activity Not Found",Toast.LENGTH_SHORT).show()
}

Si necesita otra aplicación, en lugar de mostrar Toast puede mostrar un cuadro de diálogo. Mediante el diálogo puede llevar al usuario a Play-Store para descargar la aplicación requerida.

Vignesh KM
fuente
com.android.settings.fuelgauge.PowerUsageSummaryes solo un alias de actividadcom.android.settings.Settings$PowerUsageSummaryActivity , y se eliminó en Android Pie , así que culminé la edición para hacer que esta respuesta se adapte a Pie. Tenga en cuenta que también es compatible con la versión anterior, consulte AOSP commit el 10 de noviembre de 2011 af9252849fd94c1f2859c56a4010900ea38a607e, etc.
Fin de semana
3

Si conoce los datos y la acción a la que reacciona el paquete instalado, simplemente debe agregar esta información a su instancia de intención antes de comenzar.

Si tiene acceso al Manifiesto de Android de la otra aplicación, puede ver toda la información necesaria allí.

WarrenFe
fuente
1
Gracias por la respuesta. Sí, tengo el AndroidManifest de la otra aplicación. Lo que intento hacer ahora es el siguiente código: Intención intención = nueva intención (Intent.ACTION_MAIN); intent.setComponent (nuevo ComponentName ("com.package", ". MainActivity")); startActivity (intento); pero de esta manera no está funcionando. ¿Me puede dar un enlace más preciso, cómo hacerlo?
Bastian
1
La aplicación se bloquea en la línea "startActivity ...": la aplicación se ha detenido inesperadamente. Por favor intente nuevamente. ¿Dónde puedo ver el error en LogCat?
Bastian
55
Encontré el error: al configurar el componente, debe nombrarse el nombre de clase completo en lugar de solo la clase: intent.setComponent (nuevo ComponentName ("com.package", "com.package.MainActivity")) en lugar de intento .setComponent (nuevo ComponentName ("com.package", ". MainActivity"))
Bastian
1
Es bueno saberlo ... Puede encontrar LogCat en eclipse: Ventana> Mostrar vista> Otro, Android> Logcat
WarrenFaith
@WarrenFaith Necesito soporte con stackoverflow.com/questions/52335402/… Por favor, ayuda.
user158
2

Pasos para lanzar una nueva actividad de la siguiente manera:

1.Obtener intención para el paquete

2. Si la intención es nula, redirija al usuario a PlayStore

3. Si la intención no es una actividad abierta nula

public void launchNewActivity(Context context, String packageName) {
    Intent intent = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.CUPCAKE) {
        intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
    }
    if (intent == null) {
        try {
            intent = new Intent(Intent.ACTION_VIEW);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setData(Uri.parse("market://details?id=" + packageName));
            context.startActivity(intent);
        } catch (android.content.ActivityNotFoundException anfe) {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + packageName)));
        }
    } else {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
}
Sharath kumar
fuente
2

Es posible iniciar la actividad de una aplicación usando Intent.setClassName acuerdo con los documentos.

Un ejemplo:

val activityName = "com.google.android.apps.muzei.MuzeiActivity" // target activity name
val packageName = "net.nurik.roman.muzei" // target package's name
val intent = Intent().setClassName(packageName, activityName)
startActivity(intent)

Para abrirlo fuera de la aplicación actual, agregue esta bandera antes de comenzar la intención.

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

Una respuesta relacionada aquí

Phani Rithvij
fuente
pls cómo escribir en C ++.
GeneCode
1
@GeneCode stackoverflow.com/a/22436147/8608146 podría ayudarme nunca antes había trabajado con libras de C ++ en Android.
Phani Rithvij
1
private fun openOtherApp() {
        val sendIntent = packageManager.getLaunchIntentForPackage("org.mab.dhyanaqrscanner")
        startActivity(sendIntent)
        finishAffinity()
    }
Mirza Ahmed Baig
fuente