วิธีกรองแอปเฉพาะสำหรับเจตนา ACTION_SEND (และตั้งค่าข้อความที่แตกต่างกันสำหรับแต่ละแอป)


187

คุณจะกรองแอพที่เจาะจงเมื่อใช้ ACTION_SEND ได้อย่างไร คำถามนี้ถูกถามในรูปแบบต่าง ๆ แต่ฉันไม่สามารถรวบรวมโซลูชันตามคำตอบที่ได้รับ หวังว่าบางคนสามารถช่วยได้ ฉันต้องการมอบความสามารถในการแบ่งปันภายในแอพ ทำตามคำแนะนำของ Android Dev Alexander Lucasฉันต้องการทำโดยใช้ intents และไม่ใช้ Facebook / Twitter API

การแชร์โดยใช้เจตนา ACTION_SEND

การแชร์โดยใช้เจตนา ACTION_SEND นั้นยอดเยี่ยม แต่ปัญหาคือ (1) ฉันไม่ต้องการตัวเลือกการแชร์ทุกครั้งที่นั่นฉันควร จำกัด ให้ FB, Twitter และอีเมลและ (2) ฉันไม่ต้องการแชร์ สิ่งเดียวกันกับแต่ละแอปที่ใช้ร่วมกัน ตัวอย่างเช่นในการแบ่งปันทวิตเตอร์ของฉันฉันจะรวมถึงการกล่าวถึงและแฮชแท็ก จำกัด ไว้ที่ 140 ตัวอักษรหรือน้อยกว่าในขณะที่ส่วนแบ่ง Facebook จะรวมลิงค์และภาพคุณสมบัติ

เป็นไปได้ไหมที่จะ จำกัด ตัวเลือกสำหรับเจตนา ACTION_SEND (ใช้ร่วมกัน)? ฉันเห็นบางอย่างเกี่ยวกับการใช้ PackageManager และ queryIntentActivities แต่ไม่สามารถเข้าใจการเชื่อมต่อระหว่าง PackageManager และเจตนา ACTION_SEND ได้

หรือ

แทนที่จะกรองแอปที่แชร์ปัญหาของฉันก็สามารถแก้ไขได้หากฉันสามารถใช้ความตั้งใจ ACTION_SEND เพื่อไปที่ facebook หรือ twitter โดยตรงแทนที่จะเปิดหน้าต่างโต้ตอบ หากเป็นกรณีนั้นฉันสามารถสร้างกล่องโต้ตอบของตัวเองและเมื่อพวกเขาคลิก "Facebook" สร้างเจตนาเฉพาะของ Facebook และเพียงส่งพวกเขาไปยัง Facebook เหมือนกันกับ Twitter

หรือมันเป็นไปไม่ได้? API ของ Facebook และ Twitter เป็นวิธีเดียวหรือไม่


ซ้ำซ้อนที่เป็นไปได้: [กำหนดเองกรองความตั้งใจเลือกตามติดตั้งหุ่นยนต์ชื่อแพคเกจ] [1] [1]: stackoverflow.com/questions/5734678/ …
Asaf Pinhassi

1
โพสต์บล็อกนี้น่าจะเป็นคำตอบที่สมบูรณ์แบบ: hkdevtips.blogspot.com/2013/02/..
Vitali Olshevski

2
เฮ้เพื่อน ... เมื่อฉันคลิกปุ่มส่งของฉันจากนั้นเปิดกล่องโต้ตอบแชร์และแชร์รายการคือ "gmail, email, zapiya, hookup" เป็นต้น แต่ไม่แสดง Facebook, Whatsapp, Facebook Messanger, Hangouts ธุดงค์ ... ฉันจะแสดงมันได้ยังไง?
GB_Bhayani ツ

วิธีการไม่แสดงตัวเลือกเมื่อมีเพียงหนึ่งรายการ / ตัวเลือกของการกระทำที่ตั้งใจใน Android 6.0? ปัญหาไม่แสดงบน Android ที่น้อยกว่า 6.0
zys

คำตอบ:


324

สำหรับความรู้ของฉัน StackOverflow มีผู้คนมากมายที่ถามคำถามนี้ด้วยวิธีการต่าง ๆ แต่ยังไม่มีใครตอบคำถามได้อย่างสมบูรณ์

สเป็คของฉันเรียกร้องให้ผู้ใช้สามารถเลือกอีเมล, Twitter, Facebook หรือ SMS พร้อมข้อความที่กำหนดเองสำหรับแต่ละคน นี่คือวิธีที่ฉันทำสำเร็จ:

public void onShareClick(View v) {
    Resources resources = getResources();

    Intent emailIntent = new Intent();
    emailIntent.setAction(Intent.ACTION_SEND);
    // Native email client doesn't currently support HTML, but it doesn't hurt to try in case they fix it
    emailIntent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_native)));
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));
    emailIntent.setType("message/rfc822");

    PackageManager pm = getPackageManager();
    Intent sendIntent = new Intent(Intent.ACTION_SEND);     
    sendIntent.setType("text/plain");


    Intent openInChooser = Intent.createChooser(emailIntent, resources.getString(R.string.share_chooser_text));

    List<ResolveInfo> resInfo = pm.queryIntentActivities(sendIntent, 0);
    List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();        
    for (int i = 0; i < resInfo.size(); i++) {
        // Extract the label, append it, and repackage it in a LabeledIntent
        ResolveInfo ri = resInfo.get(i);
        String packageName = ri.activityInfo.packageName;
        if(packageName.contains("android.email")) {
            emailIntent.setPackage(packageName);
        } else if(packageName.contains("twitter") || packageName.contains("facebook") || packageName.contains("mms") || packageName.contains("android.gm")) {
            Intent intent = new Intent();
            intent.setComponent(new ComponentName(packageName, ri.activityInfo.name));
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("text/plain");
            if(packageName.contains("twitter")) {
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_twitter));
            } else if(packageName.contains("facebook")) {
                // Warning: Facebook IGNORES our text. They say "These fields are intended for users to express themselves. Pre-filling these fields erodes the authenticity of the user voice."
                // One workaround is to use the Facebook SDK to post, but that doesn't allow the user to choose how they want to share. We can also make a custom landing page, and the link
                // will show the <meta content ="..."> text from that page with our link in Facebook.
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_facebook));
            } else if(packageName.contains("mms")) {
                intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.share_sms));
            } else if(packageName.contains("android.gm")) { // If Gmail shows up twice, try removing this else-if clause and the reference to "android.gm" above
                intent.putExtra(Intent.EXTRA_TEXT, Html.fromHtml(resources.getString(R.string.share_email_gmail)));
                intent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.share_email_subject));               
                intent.setType("message/rfc822");
            }

            intentList.add(new LabeledIntent(intent, packageName, ri.loadLabel(pm), ri.icon));
        }
    }

    // convert intentList to array
    LabeledIntent[] extraIntents = intentList.toArray( new LabeledIntent[ intentList.size() ]);

    openInChooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, extraIntents);
    startActivity(openInChooser);       
}

ฉันพบบิตของวิธีการทำเช่นนี้ในสถานที่ต่าง ๆ แต่ฉันไม่ได้เห็นมันทั้งหมดในที่เดียวที่อื่น

โปรดทราบว่าวิธีนี้ยังซ่อนตัวเลือกโง่ ๆ ทั้งหมดที่ฉันไม่ต้องการเช่นการแชร์ผ่าน wifi และบลูทู ธ

หวังว่านี่จะช่วยใครซักคน

แก้ไข: ในความคิดเห็นฉันถูกขอให้อธิบายว่ารหัสนี้ทำอะไร โดยพื้นฐานแล้วมันเป็นการสร้างความACTION_SENDตั้งใจให้กับไคลเอนต์อีเมลพื้นฐานเท่านั้นจากนั้นจึงทำการแทรกความตั้งใจอื่น ๆ ลงบนตัวเลือก การสร้างความตั้งใจเฉพาะทางอีเมลดั้งเดิมกำจัดขยะพิเศษทั้งหมดเช่น wifi และ bluetooth จากนั้นฉันก็คว้าสิ่งอื่นที่ฉันต้องการจากACTION_SENDข้อความธรรมดาประเภททั่วไปและตรึงมันไว้ก่อนที่จะแสดงตัวเลือก

เมื่อฉันเพิ่มความตั้งใจเพิ่มเติมฉันจะกำหนดข้อความที่กำหนดเองสำหรับแต่ละรายการ

Edit2:นานมานี้ตั้งแต่ฉันโพสต์สิ่งนี้และสิ่งต่าง ๆ เปลี่ยนไปเล็กน้อย หากคุณเห็น gmail สองครั้งในรายการตัวเลือกให้ลองลบการจัดการพิเศษสำหรับ "android.gm" ตามที่แนะนำในความคิดเห็นโดย @h_k ด้านล่าง

เนื่องจากคำตอบเดียวนี้เป็นที่มาของคะแนนชื่อเสียงสแต็คโอเวอร์โฟลว์เกือบทั้งหมดของฉันฉันจึงต้องพยายามปรับปรุงให้ทันสมัยอยู่เสมอ


1
ฉันกำลังใช้รหัสนี้ แต่อย่างใด Evernote กำลังแอบเข้าไปในรายการ เมื่อฉันตรวจสอบชื่อแพ็คเกจมันเป็น com.evernote ดังนั้นฉันไม่แน่ใจว่าทำไมสิ่งนี้จึงเกิดขึ้น
James Harpe

1
@ user2249287 ฉันขอแนะนำให้คุณดำเนินการตามรหัสจนกว่าคุณจะเห็นแอพการส่งข้อความที่ถูกข้ามไปแล้วดูที่ชื่อแพ็กเกจเพื่อพิจารณาว่าสตริงใดที่คุณต้องการเพิ่มในรายการที่อนุญาตที่จะปรากฏ
dacoinminster

1
@Gilbou สวัสดี! ขออภัยนานมากแล้วที่ฉันดูรหัสนี้ . . ขณะที่ฉันจำคำสั่ง setPackage เลือกเจตนาเดียวซึ่งคุณจะผนวกทุกอย่างอื่น ในการรวมหรือแยกการแสดงอื่น ๆ ที่หลากหลายฉันขอแนะนำให้คุณลองดูรหัสและดูที่ชื่อแพ็คเกจ
dacoinminster

2
เพื่อกรองเฉพาะอีเมลปพลิเคชันที่ผู้ใช้มีคุณสามารถใช้คำตอบที่สองจากคำถามนี้: stackoverflow.com/questions/8701634/send-email-intent ไม่ต้องการใช้ชนิดข้อมูลของข้อความ / rfc822 ซึ่งแอพอื่นเช่น EverNote ในกรณีนี้ใช้ด้วย
mpellegr

2
@dacoinminster รหัสของคุณยอดเยี่ยมมากที่ให้ฉันกำหนดข้อความที่แตกต่างสำหรับแอพอย่าง Twitter และ Whatsapp ในการลบ gmail ที่ซ้ำกันฉันเพิ่งเอา "android.gm" ออกจากสมการ ฉันยังได้รับ gmail และแอปอีเมลในตัวในรายการตัวเลือกและหัวเรื่องและข้อความยังคงไม่เปลี่ยนแปลง
h_k

26

หากคุณต้องการตัวเลือกที่กำหนดเองคุณไม่ควรพึ่งพากล่องโต้ตอบเริ่มต้นที่ได้รับจาก Android สำหรับการกระทำนี้

สิ่งที่คุณต้องทำคือการเปิดตัวของคุณเอง คุณจะต้องสอบถามPackageManagerที่แพ็คเกจจัดการกับการกระทำที่คุณต้องการจากนั้นตามการตอบกลับคุณใช้การกรองและข้อความที่กำหนดเอง

โดยเฉพาะให้ดูที่วิธีการที่queryIntentActivitiesของPackageManagerระดับ คุณสร้างความตั้งใจที่จะเปิดใช้กล่องโต้ตอบเริ่มต้น (เจตนา ACTION_SEND) ส่งต่อไปยังวิธีนี้และคุณจะได้รับรายการวัตถุที่มีข้อมูลเกี่ยวกับกิจกรรมที่สามารถจัดการความตั้งใจนั้นได้ คุณสามารถเลือกสิ่งที่คุณต้องการได้

เมื่อคุณสร้างรายการแพคเกจที่คุณต้องการนำเสนอคุณจะต้องสร้างกล่องโต้ตอบรายการของคุณเอง (โดยเฉพาะอย่างยิ่งกิจกรรมที่มีชุดรูปแบบการโต้ตอบ) ซึ่งจะแสดงรายการนั้น

สิ่งหนึ่งที่ควรทราบก็คือว่ามันยากมากที่จะทำให้การโต้ตอบที่กำหนดเองที่ดูเหมือนว่าเป็นค่าเริ่มต้น ปัญหาคือชุดรูปแบบที่ใช้ในกล่องโต้ตอบนั้นเป็นชุดรูปแบบภายในและไม่สามารถใช้งานได้โดยแอปพลิเคชันของคุณ คุณสามารถลองทำให้มันดูคล้ายกับของพื้นเมืองได้ตามที่คุณต้องการหรือไปดูแบบกำหนดเองโดยสมบูรณ์ (แอพหลายตัวทำเช่นแอพแกลเลอรี่ ฯลฯ )


1
การทำเครื่องหมายคำตอบนี้ให้ถูกต้องเนื่องจากมันตอบคำถามเดิมอย่างใกล้ชิดที่สุดแม้ว่าฉันจะไปเส้นทางอื่น (ดูคำตอบของฉัน) ขอบคุณ
Kyle Clegg

22

ลองอันนี้เพื่อแชร์เพียงสามแอพ - Facebook, Twitter, KakaoStory

public void onShareClick(View v){
    List<Intent> targetShareIntents=new ArrayList<Intent>();
    Intent shareIntent=new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.setType("text/plain");
    List<ResolveInfo> resInfos=getPackageManager().queryIntentActivities(shareIntent, 0);
    if(!resInfos.isEmpty()){
        System.out.println("Have package");
        for(ResolveInfo resInfo : resInfos){
            String packageName=resInfo.activityInfo.packageName;
            Log.i("Package Name", packageName);
            if(packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana") || packageName.contains("com.kakao.story")){
                Intent intent=new Intent();
                intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
                intent.setAction(Intent.ACTION_SEND);
                intent.setType("text/plain");
                intent.putExtra(Intent.EXTRA_TEXT, "Text");
                intent.putExtra(Intent.EXTRA_SUBJECT, "Subject");
                intent.setPackage(packageName);
                targetShareIntents.add(intent);
            }
        }
        if(!targetShareIntents.isEmpty()){
            System.out.println("Have Intent");
            Intent chooserIntent=Intent.createChooser(targetShareIntents.remove(0), "Choose app to share");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
            startActivity(chooserIntent);
        }else{
            System.out.println("Do not Have Intent");
            showDialaog(this);
        }
    }
}

รหัสนี้ทำงานได้อย่างสมบูรณ์แบบถ้าคุณพยายามที่จะแชร์กับแอพเฉพาะ
Orcun Sevsay

22

พบวิธีแก้ปัญหาที่เหมาะกับฉันที่นี่ (ดูความคิดเห็นที่สามของคำตอบแรก) รหัสนี้จะค้นหาไคลเอนต์ twitter ที่ถูกต้องและใช้มันเพื่อโพสต์ทวีต หมายเหตุ: มันไม่ได้ให้ความตั้งใจแก่ลูกค้า Twitter ต่างๆและให้คุณเลือก

แบ่งปันโดยใช้ Twitter:

Intent shareIntent = findTwitterClient(); 
shareIntent.putExtra(Intent.EXTRA_TEXT, "test");
startActivity(Intent.createChooser(shareIntent, "Share"));

เรียกวิธีนี้:

public Intent findTwitterClient() {
    final String[] twitterApps = {
            // package // name - nb installs (thousands)
            "com.twitter.android", // official - 10 000
            "com.twidroid", // twidroid - 5 000
            "com.handmark.tweetcaster", // Tweecaster - 5 000
            "com.thedeck.android" }; // TweetDeck - 5 000 };
    Intent tweetIntent = new Intent();
    tweetIntent.setType("text/plain");
    final PackageManager packageManager = getPackageManager();
    List<ResolveInfo> list = packageManager.queryIntentActivities(
            tweetIntent, PackageManager.MATCH_DEFAULT_ONLY);

    for (int i = 0; i < twitterApps.length; i++) {
        for (ResolveInfo resolveInfo : list) {
            String p = resolveInfo.activityInfo.packageName;
            if (p != null && p.startsWith(twitterApps[i])) {
                tweetIntent.setPackage(p);
                return tweetIntent;
            }
        }
    }

    return null;
}

Facebook จะคล้ายกันโดยใช้ " com.facebook.katana " แม้ว่าคุณจะยังไม่สามารถตั้งค่าข้อความ (เลิกใช้กรกฎาคม 2011)

รหัสแหล่งที่มา: ตั้งใจที่จะเปิดไคลเอนต์ Twitter บน Android


4
ฉันไม่ชอบคำตอบนี้เพราะขึ้นอยู่กับการรู้ชื่อแพ็คเกจของแอพตัวสั่นด้วยความตื่นเต้นทั้งหมด สำหรับวิธีอื่นดูstackoverflow.com/questions/6827407/…
Ed Burnette

ฉันเห็นด้วยกับคุณแม้ว่าคำตอบที่คุณเชื่อมโยงนั้นมีปัญหาคล้ายกัน ฉันไม่ชอบอาศัยการเปรียบเทียบสตริงโดยเฉพาะเมื่อฉันไม่มีการควบคุมหรือรับประกันว่าสตริงจะไม่เปลี่ยนแปลง
Kyle Clegg

11

ขอบคุณ @dacoinminster ฉันทำการแก้ไขคำตอบของเขารวมถึงชื่อแพ็คเกจของแอพยอดนิยมและการเรียงลำดับแอพเหล่านั้น

List<Intent> targetShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> resInfos = pm.queryIntentActivities(shareIntent, 0);
if (!resInfos.isEmpty()) {
    System.out.println("Have package");
    for (ResolveInfo resInfo : resInfos) {
        String packageName = resInfo.activityInfo.packageName;
        Log.i("Package Name", packageName);

        if (packageName.contains("com.twitter.android") || packageName.contains("com.facebook.katana")
                || packageName.contains("com.whatsapp") || packageName.contains("com.google.android.apps.plus")
                || packageName.contains("com.google.android.talk") || packageName.contains("com.slack")
                || packageName.contains("com.google.android.gm") || packageName.contains("com.facebook.orca")
                || packageName.contains("com.yahoo.mobile") || packageName.contains("com.skype.raider")
                || packageName.contains("com.android.mms")|| packageName.contains("com.linkedin.android")
                || packageName.contains("com.google.android.apps.messaging")) {
            Intent intent = new Intent();

            intent.setComponent(new ComponentName(packageName, resInfo.activityInfo.name));
            intent.putExtra("AppName", resInfo.loadLabel(pm).toString());
            intent.setAction(Intent.ACTION_SEND);
            intent.setType("text/plain");
            intent.putExtra(Intent.EXTRA_TEXT, "https://website.com/");
            intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_text));
            intent.setPackage(packageName);
            targetShareIntents.add(intent);
        }
    }
    if (!targetShareIntents.isEmpty()) {
        Collections.sort(targetShareIntents, new Comparator<Intent>() {
            @Override
            public int compare(Intent o1, Intent o2) {
                return o1.getStringExtra("AppName").compareTo(o2.getStringExtra("AppName"));
            }
        });
        Intent chooserIntent = Intent.createChooser(targetShareIntents.remove(0), "Select app to share");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetShareIntents.toArray(new Parcelable[]{}));
        startActivity(chooserIntent);
    } else {
        Toast.makeText(getActivity(), "No app to share.", Toast.LENGTH_LONG).show();
    }
}

9

คุณสามารถลองโค้ดด้านล่างมันทำงานได้อย่างสมบูรณ์

ที่นี่เราแชร์บางแอปเฉพาะที่เป็น Facebook, Messenger, Twitter, Google Plus และ Gmail

public void shareIntentSpecificApps() {
        List<Intent> intentShareList = new ArrayList<Intent>();
        Intent shareIntent = new Intent();
        shareIntent.setAction(Intent.ACTION_SEND);
        shareIntent.setType("text/plain");
        List<ResolveInfo> resolveInfoList = getPackageManager().queryIntentActivities(shareIntent, 0);

        for (ResolveInfo resInfo : resolveInfoList) {
            String packageName = resInfo.activityInfo.packageName;
            String name = resInfo.activityInfo.name;
            Log.d(TAG, "Package Name : " + packageName);
            Log.d(TAG, "Name : " + name);

            if (packageName.contains("com.facebook") ||
                    packageName.contains("com.twitter.android") ||
                    packageName.contains("com.google.android.apps.plus") ||
                    packageName.contains("com.google.android.gm")) {

                if (name.contains("com.twitter.android.DMActivity")) {
                    continue;
                }

                Intent intent = new Intent();
                intent.setComponent(new ComponentName(packageName, name));
                intent.setAction(Intent.ACTION_SEND);
                intent.setType("text/plain");
                intent.putExtra(Intent.EXTRA_SUBJECT, "Your Subject");
                intent.putExtra(Intent.EXTRA_TEXT, "Your Content");
                intentShareList.add(intent);
            }
        }

        if (intentShareList.isEmpty()) {
            Toast.makeText(MainActivity.this, "No apps to share !", Toast.LENGTH_SHORT).show();
        } else {
            Intent chooserIntent = Intent.createChooser(intentShareList.remove(0), "Share via");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentShareList.toArray(new Parcelable[]{}));
            startActivity(chooserIntent);
        }
    }

อะไรคือสาเหตุของ "if (name.contain (" com.twitter.android.DMActivity ")) {ดำเนินการต่อ;}?
isJulian00

8

โซลูชันนี้แสดงรายการแอปพลิเคชั่นในกล่องโต้ตอบ ListView ที่คล้ายกับตัวเลือก:

ภาพหน้าจอ

มันขึ้นอยู่กับคุณถึง:

  1. รับรายการแพ็คเกจแอปพลิเคชันที่เกี่ยวข้อง
  2. ระบุชื่อแพ็คเกจเรียกใช้เจตนาที่เกี่ยวข้อง

คลาสอะแดปเตอร์:

import java.util.List;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class ChooserArrayAdapter extends ArrayAdapter<String> {
    PackageManager mPm;
    int mTextViewResourceId;
    List<String> mPackages;

    public ChooserArrayAdapter(Context context, int resource, int textViewResourceId, List<String> packages) {
        super(context, resource, textViewResourceId, packages);
        mPm = context.getPackageManager();
        mTextViewResourceId = textViewResourceId;
        mPackages = packages;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        String pkg = mPackages.get(position);
        View view = super.getView(position, convertView, parent);

        try {
            ApplicationInfo ai = mPm.getApplicationInfo(pkg, 0);

            CharSequence appName = mPm.getApplicationLabel(ai);
            Drawable appIcon = mPm.getApplicationIcon(pkg);

            TextView textView = (TextView) view.findViewById(mTextViewResourceId);
            textView.setText(appName);
            textView.setCompoundDrawablesWithIntrinsicBounds(appIcon, null, null, null);
            textView.setCompoundDrawablePadding((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getContext().getResources().getDisplayMetrics()));
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }

        return view;
    }

}

และการใช้งาน:

    void doXxxButton() {
        final List<String> packages = ...;
        if (packages.size() > 1) {
            ArrayAdapter<String> adapter = new ChooserArrayAdapter(MyActivity.this, android.R.layout.select_dialog_item, android.R.id.text1, packages);

            new AlertDialog.Builder(MyActivity.this)
            .setTitle(R.string.app_list_title)
            .setAdapter(adapter, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int item ) {
                    invokeApplication(packages.get(item));
                }
            })
            .show();
        } else if (packages.size() == 1) {
            invokeApplication(packages.get(0));
        }
    }

    void invokeApplication(String packageName) {
        // given a package name, create an intent and fill it with data
        ...
        startActivityForResult(intent, rq);
    }

4

วิธีที่สะอาดที่สุดคือการคัดลอกคลาสต่อไปนี้: ShareActionProvider, ActivityChooserView, ActivityChooserModel เพิ่มความสามารถในการกรอง intents ใน ActivityChooserModel และวิธีการสนับสนุนที่เหมาะสมใน ShareActionProvider ฉันสร้างคลาสที่จำเป็นคุณสามารถคัดลอกคลาสเหล่านั้นลงในโครงการของคุณ ( https://gist.github.com/saulpower/10557956 ) สิ่งนี้ไม่เพียงเพิ่มความสามารถในการกรองแอพที่คุณต้องการแชร์ด้วย (ถ้าคุณรู้ชื่อแพ็คเกจ) แต่ยังสามารถปิดประวัติได้ด้วย

private final String[] INTENT_FILTER = new String[] {
    "com.twitter.android",
    "com.facebook.katana"
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.journal_entry_menu, menu);

    // Set up ShareActionProvider's default share intent
    MenuItem shareItem = menu.findItem(R.id.action_share);

    if (shareItem instanceof SupportMenuItem) {
        mShareActionProvider = new ShareActionProvider(this);
        mShareActionProvider.setShareIntent(ShareUtils.share(mJournalEntry));
        mShareActionProvider.setIntentFilter(Arrays.asList(INTENT_FILTER));
        mShareActionProvider.setShowHistory(false);
        ((SupportMenuItem) shareItem).setSupportActionProvider(mShareActionProvider);
    }

    return super.onCreateOptionsMenu(menu);
}

วิธีเพิ่ม google + และตัวเลือกอื่น ๆ ที่มีแอปพลิเคชั่น
remaing

3

ฉันได้รับคำตอบ @dacoinminster ที่ปรับปรุงแล้วและนี่คือผลลัพธ์พร้อมตัวอย่างเพื่อแชร์แอปของคุณ:

// Intents with SEND action
PackageManager packageManager = context.getPackageManager();
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(sendIntent, 0);

List<LabeledIntent> intentList = new ArrayList<LabeledIntent>();
Resources resources = context.getResources();

for (int j = 0; j < resolveInfoList.size(); j++) {
    ResolveInfo resolveInfo = resolveInfoList.get(j);
    String packageName = resolveInfo.activityInfo.packageName;
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_SEND);
    intent.setComponent(new ComponentName(packageName,
    resolveInfo.activityInfo.name));
    intent.setType("text/plain");

    if (packageName.contains("twitter")) {
        intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.twitter) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
    } else {
        // skip android mail and gmail to avoid adding to the list twice
        if (packageName.contains("android.email") || packageName.contains("android.gm")) {
            continue;
        }
        intent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForFacebookWhatsapp) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());
    }

    intentList.add(new LabeledIntent(intent, packageName, resolveInfo.loadLabel(packageManager), resolveInfo.icon));
}

Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"));
emailIntent.putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.subjectForMailApps));
emailIntent.putExtra(Intent.EXTRA_TEXT, resources.getString(R.string.largeTextForMailApps) + "https://play.google.com/store/apps/details?id=" + context.getPackageName());

context.startActivity(Intent.createChooser(emailIntent, resources.getString(R.string.compartirEn)).putExtra(Intent.EXTRA_INITIAL_INTENTS, intentList.toArray(new LabeledIntent[intentList.size()])));

3

ฉันมีปัญหาเดียวกันและวิธีแก้ปัญหาที่ยอมรับนี้ไม่ได้ช่วยฉันถ้ามีคนมีปัญหาเดียวกันคุณสามารถใช้ข้อมูลโค้ดของฉัน :

// example of filtering and sharing multiple images with texts
// remove facebook from sharing intents
private void shareFilter(){

    String share = getShareTexts();
    ArrayList<Uri> uris = getImageUris();

    List<Intent> targets = new ArrayList<>();
    Intent template = new Intent(Intent.ACTION_SEND_MULTIPLE);
    template.setType("image/*");
    List<ResolveInfo> candidates = getActivity().getPackageManager().
            queryIntentActivities(template, 0);

    // remove facebook which has a broken share intent
    for (ResolveInfo candidate : candidates) {
        String packageName = candidate.activityInfo.packageName;
        if (!packageName.equals("com.facebook.katana")) {
            Intent target = new Intent(Intent.ACTION_SEND_MULTIPLE);
            target.setType("image/*");
            target.putParcelableArrayListExtra(Intent.EXTRA_STREAM,uris);
            target.putExtra(Intent.EXTRA_TEXT, share);
            target.setPackage(packageName);
            targets.add(target);
        }
    }
    Intent chooser = Intent.createChooser(targets.remove(0), "Share Via");
    chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[targets.size()]));
    startActivity(chooser);

}


0

ง่ายและกระชับ ขอขอบคุณผู้พัฒนาโอเพนซอร์ซ cketti ที่แบ่งปันโซลูชันนี้:

String mailto = "mailto:bob@example.org" +
    "?cc=" + "alice@example.com" +
    "&subject=" + Uri.encode(subject) +
    "&body=" + Uri.encode(bodyText);

Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
emailIntent.setData(Uri.parse(mailto));

try {
  startActivity(emailIntent);
} catch (ActivityNotFoundException e) {
  //TODO: Handle case where no email app is available
}

และนี่คือลิงค์ไปยังส่วนสำคัญของเขา / เธอ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.