Cách khởi chạy một Hoạt động từ một Ứng dụng khác trong Android


478

Tôi muốn khởi chạy gói cài đặt từ ứng dụng Android của mình. Tôi cho rằng có thể sử dụng ý định, nhưng tôi không tìm ra cách nào để làm điều đó. Có một liên kết, nơi để tìm thông tin?


2
Điều gì xảy ra nếu tôi mở ứng dụng thứ hai từ ứng dụng thứ nhất và sau đó nhấp trực tiếp vào biểu tượng của ứng dụng thứ hai, tôi nhận được hai phiên bản của ứng dụng, đó là điều không mong muốn. Làm thế nào để quản lý nó ??
Radhey

Câu trả lời:


707

Nếu bạn không biết hoạt động chính, thì tên gói có thể được sử dụng để khởi chạy ứng dụng.

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) { 
    startActivity(launchIntent);//null pointer check in case package name was not found
}

5
Bất kỳ lý do tại sao điều này sẽ không làm việc? Tôi đã không làm cho nó hoạt động ít nhất.
Simon Forsberg

22
Nó bắt đầu một Ý định mới, làm thế nào để tiếp tục ứng dụng đang ở chế độ nền?
Salil Dua

3
@andep: Điều này hoạt động tốt với tôi khi tôi thử nghiệm giữa hai ứng dụng do tôi tự tạo. Một khi tôi biết tên gói này sẽ luôn hoạt động, hoặc có cách nào để ngăn người khác khởi chạy ứng dụng của bạn (trong trạng thái manly hoặc ở đâu đó) không?
Leonard Chargehan

2
@Leonard: Ấn tượng đầu tiên của tôi, rằng nó phải luôn hoạt động, vì tên gói được công khai để bất kỳ ứng dụng nào cũng có thể đọc chúng. Từ các ứng dụng của bạn, tôi nghĩ rằng bạn không thể xác định được nó được gọi từ đâu nhưng ứng dụng của bạn có thể xác định rằng nó không thể được gọi thông qua hoạt động chính chỉ thông qua các dịch vụ.
andep

1
Vâng, điều này có thể trả về null. "Việc triển khai hiện tại trông đầu tiên cho một hoạt động chính trong danh mục CATEGORY_INFOvà tiếp theo là một hoạt động chính trong danh mục CATEGORY_LAUNCHER. Trả về null nếu không tìm thấy. "
quietmint

239

Tôi biết điều này đã được trả lời nhưng đây là cách tôi thực hiện một cái gì đó tương tự:

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);
}

Thậm chí tốt hơn, đây là phương pháp:

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);
    }
}

Đã xóa mã trùng lặp:

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);
}

8
Tôi đã gặp sự cố khi bắt đầu Ý định vào hồ sơ Facebook hoặc Twitter. Họ đã mở bên trong ứng dụng của tôi, thay vì như một hoạt động mới. Đã thêm FLAG_ACTIVITY_NEW_TASK đã sửa. Cảm ơn!
Harry

4
Không vấn đề gì! Tôi đã gặp rắc rối với thứ gì đó rất giống
Jared Burrows

1
Phương thức này hoạt động với tôi, nhưng đôi khi Ứng dụng mới mở và Hoạt động gọi vẫn là tiền cảnh. Có ai nghĩ ra cách sửa không?
lgdroid57

Có cách nào để làm điều này từ ứng dụng tức thì không?
Mahdi

Chỉ hoạt động cho các phiên bản phát hành. Nếu bạn đang cố mở ứng dụng gỡ lỗi, ý định sẽ không có giá trị.
RexSplode

152

Tôi tìm thấy giải pháp. Trong tệp kê khai của ứng dụng, tôi tìm thấy tên gói: com.package.address và tên của hoạt động chính mà tôi muốn khởi chạy: MainActivity Đoạn mã sau khởi động ứng dụng này:

Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("com.package.address","com.package.address.MainActivity"));
startActivity(intent);

8
tôi có ngoại lệ 'liều bạn khai báo hoạt động trong Manifest.xml của bạn'
itzhar

Cách này trả về một ngoại lệ cho biết tôi cần khai báo hoạt động trong bảng kê khai của mình .. nhưng đó là một ứng dụng bên ngoài!
JJ Ab

Làm thế nào để chạy nó trong nền? Có nghĩa là các ứng dụng được gọi thứ hai không hiển thị trên màn hình, nhưng chạy phương thức onCreated () của nó.
Dr.jacky

Tôi gặp lỗi này khi tôi thử từ ứng dụng tức thời: Không được phép bắt đầu hoạt động Ý định
Mahdi

@Bastian làm thế nào để đóng ứng dụng hiện tại từ nơi chúng ta gọi là ý định mở ứng dụng khác?
Arnold Brown

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;
}

17

Dưới đây là ví dụ của tôi về việc khởi chạy trình quét mã vạch / mã QR từ ứng dụng của tôi nếu ai đó thấy nó hữu ích

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();
}

13

Chỉnh sửa tùy theo nhận xét

Trong một số phiên bản - như được đề xuất trong các nhận xét - ngoại lệ được ném có thể khác nhau.

Do đó, giải pháp dưới đây được sửa đổi một chút

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);
}

Câu trả lời gốc

Mặc dù được trả lời tốt, nhưng có một cách thực hiện khá đơn giản xử lý nếu ứng dụng không được cài đặt. Tôi làm nó như thế này

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")));
}

Thay thế "applicationId" bằng gói bạn muốn mở, chẳng hạn như com.google.maps, v.v.


Các PackageManager.getLaunchIntentForPackage(...)trở về phương pháp vô giá trị nếu tên gói không được công nhận. Nó không ném PackageManager.NameNotFoundException. Xem ở đây .
Adil Hussain

Tôi vừa thử startActivity(null)trên trình giả lập Android 10 và nó ném a NullPointerExceptionchứ không phải a PackageManager.NameNotFoundException.
Adil Hussain

Trên lưu ý 7 của tôi, nó hoạt động chính xác theo cách nó được dự định.
mayank1513

Hành vi dự định của startActivity(Intent intent)phương thức khi nó được đưa ra là null Intentvà điều gì khiến bạn nói điều đó? Tài liệu của các nhà phát triển Android chỉ nói rằng nó sẽ ném ActivityNotFoundException.
Adil Hussain

Xin chào @Adil, bạn có thể vui lòng giúp tôi với câu hỏi này không - 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);

        }

    }

Có giới hạn ký tự cho phương thức uri.parse không?
API

7

Nếu bạn muốn mở hoạt động cụ thể của một ứng dụng khác, chúng tôi có thể sử dụng ứng dụng này.

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()
}

Nếu bạn phải cần ứng dụng khác, thay vì hiển thị Toast, bạn có thể hiển thị hộp thoại. Sử dụng hộp thoại, bạn có thể đưa người dùng đến Play-Store để tải xuống ứng dụng cần thiết.


com.android.settings.fuelgauge.PowerUsageSummarychỉ là một hoạt động-alias của com.android.settings.Settings$PowerUsageSummaryActivity, và nó đã bị loại bỏ trong Android Pie , vì vậy tôi về Hội chỉnh sửa để làm cho câu trả lời phù hợp này Pie. Lưu ý rằng nó cũng tương thích với phiên bản cũ hơn, xem AOSP cam kết vào ngày 10 tháng 11 năm 2011 af9252849fd94c1f2859c56a4010900ea38a607e, v.v.
Cuối tuần

3

Nếu bạn biết dữ liệu và hành động mà gói đã cài đặt phản ứng, bạn chỉ cần thêm các thông tin này vào thể hiện ý định của mình trước khi bắt đầu.

Nếu bạn có quyền truy cập vào AndroidManifest của ứng dụng khác, bạn có thể xem tất cả thông tin cần thiết ở đó.


1
Cảm ơn vi đa trả lơi. Có, tôi có AndroidManifest của ứng dụng khác. Những gì tôi cố gắng làm bây giờ là đoạn mã sau: Ý định = Ý định mới (Intent.ACTION_MAIN); aim.setComponent (Thành phần mới ("com.package", ". MainActivity")); startActivity (ý định); nhưng theo cách này nó không hoạt động. Bạn có thể cho tôi một liên kết chính xác hơn, làm thế nào để làm điều đó?
Bastian

1
Ứng dụng gặp sự cố tại dòng "startActivity ...": Ứng dụng đã dừng đột ngột. Vui lòng thử lại. Tôi có thể thấy lỗi trong LogCat ở đâu?
Bastian

5
Tôi đã tìm thấy lỗi: Khi thiết lập thành phần, tên lớp đủ điều kiện thay vì chỉ là lớp phải được đặt tên: aim.setComponent (new ElementName ("com.package", "com.package.MainActivity")) thay vì mục đích .setComponent (Thành phần mới ("com.package", ". MainActivity"))
Bastian

1
Những điều cần biết ... Bạn có thể tìm thấy LogCat trên nhật thực: Cửa sổ> Hiển thị chế độ xem> Khác, Android> Logcat
WarrenFaith

@WarrenFaith Tôi cần hỗ trợ với stackoverflow.com/questions/52335402/ Hãy xin giúp đỡ.
dùng158

2

Các bước để khởi chạy hoạt động mới như sau:

1.Nhận ý định cho gói

2.Nếu ý định là null chuyển hướng người dùng đến playstore

3.Nếu ý định không hoạt động mở

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);
    }
}

2

Có thể bắt đầu hoạt động của một ứng dụng bằng cách sử dụng Intent.setClassNametheo các tài liệu.

Một ví dụ:

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)

Để mở nó bên ngoài ứng dụng hiện tại, hãy thêm cờ này trước khi bắt đầu ý định.

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

Một câu trả lời liên quan ở đây


làm thế nào để viết trong C ++.
GeneCode

1
@GeneCode stackoverflow.com/a/22436147/8608146 có thể giúp tôi chưa bao giờ làm việc với c ++ libs trong Android trước đây.
Phani Rithvij

1
private fun openOtherApp() {
        val sendIntent = packageManager.getLaunchIntentForPackage("org.mab.dhyanaqrscanner")
        startActivity(sendIntent)
        finishAffinity()
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.