programing tip

설치된 Android 패키지 이름을 기반으로 의도 선택기의 사용자 지정 필터링

itbloger 2021. 1. 10. 16:55
반응형

설치된 Android 패키지 이름을 기반으로 의도 선택기의 사용자 지정 필터링


기본 제공 인 텐트 선택기를 활용하여 사용자가 선택하고 실행할 수있는 사용자 지정 필터링 된 앱 목록을 표시하고 싶습니다.

설치된 패키지 목록을 얻는 방법을 알고 있습니다.

final Intent myIntent = new Intent(android.content.Intent.ACTION_MAIN);  
List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(myIntent, 0);

이 시점에서 패키지 이름에 포함 된 특정 문자열 (또는 문자열의 변형)을 기준으로 목록을 필터링하고 싶습니다.이 방법도 알아낼 수 있습니다.

그러나 여기에 내가 붙어 있습니다. 내가 아는 한, Intent.createChooser()매개 변수로 단일 대상 의도 만 사용합니다. 패키지 및 클래스 이름 등을 기반으로 의도 목록을 가져 오는 과부하가 있기를 바랐습니다. 하지만 그런 건 보이지 않습니다. 어딘가에서 그것을 놓쳤습니까?

그래서 질문은 이것이 내장 된 선택기로 할 수 있습니까, 아니면 AlertDialog Builder로 직접 구성해야합니까? 나는 나중에 피하고 싶다.

미리 감사드립니다.


선택기에 대한 유일한 추가 매개 변수는 Intent.EXTRA_INITIAL_INTENTS입니다. 설명은 다음과 같습니다.

ACTION_CHOOSER로 사용자에게 표시 될 때 추가 활동의 putExtra (String, Parcelable [])로 설정된 Intent 또는 LabeledIntent 객체의 Parcelable [].

Android 소스에서 목록에서 다른 활동을 제외하는 방법을 찾지 못했기 때문에 선택기를 사용하여 원하는 작업을 수행 할 방법이없는 것 같습니다.

편집 : 정말 쉽게 찾을 수 있습니다. ChooserActivityResolverActivity 소스 코드를 확인하십시오 . 이 수업은 다소 작습니다.


여기 내가 채찍질 한 해결책이 있습니다. 선택기의 각 선택에 대해 다른 인 텐트 데이터를 사용하기 위해 사용하지만 목록에서 인 텐트를 쉽게 제거 할 수도 있습니다. 도움이 되었기를 바랍니다:

List<Intent> targetedShareIntents = new ArrayList<Intent>();
Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
shareIntent.setType("text/plain");
List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(shareIntent, 0);
if (!resInfo.isEmpty()) {
    for (ResolveInfo resolveInfo : resInfo) {
        String packageName = resolveInfo.activityInfo.packageName;
        Intent targetedShareIntent = new Intent(android.content.Intent.ACTION_SEND);
        targetedShareIntent.setType("text/plain");
        targetedShareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "subject to be shared");
        if (TextUtils.equals(packageName, "com.facebook.katana")) {
            targetedShareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "http://link-to-be-shared.com");
        } else {
            targetedShareIntent.putExtra(android.content.Intent.EXTRA_TEXT, "text message to shared");
        }
        targetedShareIntent.setPackage(packageName);
        targetedShareIntents.add(targetedShareIntent);
    }
    Intent chooserIntent = Intent.createChooser(targetedShareIntents.remove(0), "Select app to share");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[targetedShareIntents.size()]));
    startActivity(chooserIntent);
}

편집하다

이 방법을 사용하는 동안 일부 앱의 이름을 Android 시스템으로 얻습니다. 누구 든지이 오류가 발생하면 pls는 전에 줄 아래에 추가하십시오.targetedShareIntents.add(targetedShareIntent);

 targetedShareIntent.setClassName(
                        resolveInfo.activityInfo.packageName,
                        resolveInfo.activityInfo.name);

출처 : Android 공유 의도 Twitter : 트윗 또는 쪽지로만 공유하는 방법은 무엇입니까?


이름으로 공유하려는 앱 목록을 갖도록 약간 수정했습니다. 이미 게시 한 내용과 거의 같지만 이름으로 공유 할 앱을 추가합니다.

String[] nameOfAppsToShareWith = new String[] { "facebook", "twitter", "gmail" };
String[] blacklist = new String[]{"com.any.package", "net.other.package"};
// your share intent
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "some text");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "a subject");
// ... anything else you want to add invoke custom chooser
startActivity(generateCustomChooserIntent(intent, blacklist));

private Intent generateCustomChooserIntent(Intent prototype,
            String[] forbiddenChoices)
    {
        List<Intent> targetedShareIntents = new ArrayList<Intent>();
        List<HashMap<String, String>> intentMetaInfo = new ArrayList<HashMap<String, String>>();
        Intent chooserIntent;

        Intent dummy = new Intent(prototype.getAction());
        dummy.setType(prototype.getType());
        List<ResolveInfo> resInfo = getPackageManager().queryIntentActivities(dummy,0);

        if (!resInfo.isEmpty())
        {
            for (ResolveInfo resolveInfo : resInfo)
            {
                if (resolveInfo.activityInfo == null
                        || Arrays.asList(forbiddenChoices).contains(
                                resolveInfo.activityInfo.packageName))
                    continue;
                //Get all the posible sharers
                HashMap<String, String> info = new HashMap<String, String>();
                info.put("packageName", resolveInfo.activityInfo.packageName);
                info.put("className", resolveInfo.activityInfo.name);
                String appName = String.valueOf(resolveInfo.activityInfo
                        .loadLabel(getPackageManager()));
                info.put("simpleName", appName);
                //Add only what we want
                if (Arrays.asList(nameOfAppsToShareWith).contains(
                        appName.toLowerCase()))
                {
                    intentMetaInfo.add(info);
                }
            }

            if (!intentMetaInfo.isEmpty())
            {
                // sorting for nice readability
                Collections.sort(intentMetaInfo,
                        new Comparator<HashMap<String, String>>()
                        {
                            @Override public int compare(
                                    HashMap<String, String> map,
                                    HashMap<String, String> map2)
                            {
                                return map.get("simpleName").compareTo(
                                        map2.get("simpleName"));
                            }
                        });

                // create the custom intent list
                for (HashMap<String, String> metaInfo : intentMetaInfo)
                {
                    Intent targetedShareIntent = (Intent) prototype.clone();
                    targetedShareIntent.setPackage(metaInfo.get("packageName"));
                    targetedShareIntent.setClassName(
                            metaInfo.get("packageName"),
                            metaInfo.get("className"));
                    targetedShareIntents.add(targetedShareIntent);
                }
                String shareVia = getString(R.string.offer_share_via);
                String shareTitle = shareVia.substring(0, 1).toUpperCase()
                        + shareVia.substring(1);
                chooserIntent = Intent.createChooser(targetedShareIntents
                        .remove(targetedShareIntents.size() - 1), shareTitle);
                chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,
                        targetedShareIntents.toArray(new Parcelable[] {}));
                return chooserIntent;
            }
        }

        return Intent.createChooser(prototype,
                getString(R.string.offer_share_via));
    }

Makibo가 게시 한 솔루션과 거의 동일하지만 이름을 추가하는 것만으로 공유하려는 앱을 쉽게 선택할 수 있도록 약간 추가하면 패키지 이름 등을 변경해도 문제가 발생하지 않습니다. 이. 이름을 바꾸지 않는 한.


사용자 정의 열기 선택기 구현.

풍모:

  • 앱은 알파벳 순서로 정렬됩니다.
  • 사용자가 정의한 기본 앱 처리
  • 앱 없음 케이스 처리
  • 자체 필터링

public static Intent createOpenFileIntent(Context context, String pathToFile) {
    File file = new File(pathToFile);
    String extension = extensionFromName(file.getName());
    String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
    if (mimeType == null) {
        //If android doesn't know extension we can check our own list.
        mimeType = KNOWN_MIME_TYPES.get(DataViewHelper.extensionFromName(file.getName()));
    }

    Intent openIntent = new Intent();
    openIntent.setAction(android.content.Intent.ACTION_VIEW);
    openIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    openIntent.setDataAndType(Uri.fromFile(file), mimeType);

    // 1. Check if there is a default app opener for this type of content.
    final PackageManager packageManager = context.getPackageManager();
    ResolveInfo defaultAppInfo = packageManager.resolveActivity(openIntent, PackageManager.MATCH_DEFAULT_ONLY);
    if (!defaultAppInfo.activityInfo.name.endsWith("ResolverActivity")) {
        return openIntent;
    }

    // 2. Retrieve all apps for our intent. If there are no apps - return usual already created intent.
    List<Intent> targetedOpenIntents = new ArrayList<Intent>();
    List<ResolveInfo> appInfoList = packageManager.queryIntentActivities(openIntent, PackageManager.MATCH_DEFAULT_ONLY);
    if (appInfoList.isEmpty()) {
        return openIntent;
    }

    // 3. Sort in alphabetical order, filter itself and create intent with the rest of the apps.
    Collections.sort(appInfoList, new Comparator<ResolveInfo>() {
        @Override
        public int compare(ResolveInfo first, ResolveInfo second) {
            String firstName = packageManager.getApplicationLabel(first.activityInfo.applicationInfo).toString();
            String secondName = packageManager.getApplicationLabel(second.activityInfo.applicationInfo).toString();
            return firstName.compareToIgnoreCase(secondName);
        }
    });
    for (ResolveInfo appInfo : appInfoList) {
        String packageName = appInfo.activityInfo.packageName;
        if (packageName.equals(context.getPackageName())) {
            continue;
        }

        Intent targetedOpenIntent = new Intent(android.content.Intent.ACTION_VIEW)
                .setDataAndType(Uri.fromFile(file), mimeType)
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .setPackage(packageName);
        targetedOpenIntents.add(targetedOpenIntent);
    }
    Intent chooserIntent = Intent.createChooser(targetedOpenIntents.remove(targetedOpenIntents.size() - 1), context.getString(R.string.context_menu_open_in))
            .putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedOpenIntents.toArray(new Parcelable[] {}));

    return chooserIntent;
}

public static String extensionFromName(String fileName) {
    int dotPosition = fileName.lastIndexOf('.');

    // If extension not present or empty
    if (dotPosition == -1 || dotPosition == fileName.length() - 1) {
        return "";
    } else {
        return fileName.substring(dotPosition + 1).toLowerCase(Locale.getDefault());
    }
}

나는 똑같은 일을 시도했지만 ShareActionProvider를 사용했습니다. gumbercules 게시물의 메서드는 ShareActionProvider에서 제대로 작동하지 않았기 때문에 ShareActionProvider 제안의 사용자 지정 필터링을 허용하도록 ShareActionProvider 관련 클래스를 복사하고 수정했습니다.

The only change is to the ActivityChooserModel.loadActivitiesIfNeeded() method. In my case, I wanted to filter out the YouTube package.

public static final String YOUTUBE_PACKAGE = "com.google.android.youtube";

private boolean loadActivitiesIfNeeded() {
    if (mReloadActivities && mIntent != null) {
        mReloadActivities = false;
        mActivities.clear();
        List<ResolveInfo> resolveInfos = mContext.getPackageManager()
                .queryIntentActivities(mIntent, 0);
        final int resolveInfoCount = resolveInfos.size();
        for (int i = 0; i < resolveInfoCount; i++) {
            ResolveInfo resolveInfo = resolveInfos.get(i);
            // Filter out the YouTube package from the suggestions list
            if (!resolveInfo.activityInfo.packageName.equals(YOUTUBE_PACKAGE)) {
                mActivities.add(new ActivityResolveInfo(resolveInfo));
            }
        }
        return true;
    }
    return false;
}

Code at https://github.com/danghiskhan/FilteredShareActionProvider


This solution is based on this post https://rogerkeays.com/how-to-remove-the-facebook-android-sharing-intent

// get available share intents
final String packageToBeFiltered = "com.example.com"
List<Intent> targets = new ArrayList<Intent>();
Intent template = new Intent(Intent.ACTION_SEND);
template.setType("text/plain");
List<ResolveInfo> candidates = this.getPackageManager().queryIntentActivities(template, 0);

// filter package here
for (ResolveInfo candidate : candidates) {
    String packageName = candidate.activityInfo.packageName;
    if (!packageName.equals(packageToBeFiltered)) {
    Intent target = new Intent(android.content.Intent.ACTION_SEND);
    target.setType("text/plain");
    target.putExtra(Intent.EXTRA_TEXT, "Text to share"));
    target.setPackage(packageName);
    targets.add(target);
   }
}
if (!targets.isEmpty()) {
Intent chooser = Intent.createChooser(targets.get(0), "Share dialog title goes here"));
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, targets.toArray(new Parcelable[]{}));
startActivity(chooser);
}

ReferenceURL : https://stackoverflow.com/questions/5734678/custom-filtering-of-intent-chooser-based-on-installed-android-package-name

반응형