How to get default device assistance app in androi

2019-08-02 04:28发布

问题:

my phone installed two voice searches: google app and S-voice app. The default app is S-voice app as figure bellow. My question is that how can we get the default voice application using programmingcally in Android 6.0. Thank you in advance

This is what I did

private boolean isMyAppLauncherDefault(String myPackageName) {
    final IntentFilter filter = new IntentFilter(Intent.ACTION_MAIN);
    filter.addCategory(Intent.CATEGORY_HOME);

    List<IntentFilter> filters = new ArrayList<IntentFilter>();
    filters.add(filter);
    List<ComponentName> activities = new ArrayList<ComponentName>();
    final PackageManager packageManager = (PackageManager) getPackageManager();

    packageManager.getPreferredActivities(filters, activities, null);
    for (ComponentName activity : activities) {

        Log.d(TAG,"======packet default:==="+activity.getPackageName());
    }
    for (ComponentName activity : activities) {

        if (myPackageName.equals(activity.getPackageName())) {
            return true;
        }
    }
    return false;
}

The above function is alway return true when my input is com.samsung.voiceserviceplatform. In other hands, the default app always returns com.google.android.googlequicksearchbox (indicates google voice)

回答1:

The DefaultAssistPreference uses an hidden method of AssistUtils to retrieve the current Assist. You can use the same method using reflection:

public ComponentName getCurrentAssistWithReflection(Context context) {
    try {
        Method myUserIdMethod = UserHandle.class.getDeclaredMethod("myUserId");
        myUserIdMethod.setAccessible(true);
        Integer userId = (Integer) myUserIdMethod.invoke(null);

        if (userId != null) {
            Constructor constructor = Class.forName("com.android.internal.app.AssistUtils").getConstructor(Context.class);
            Object assistUtils = constructor.newInstance(context);

            Method getAssistComponentForUserMethod = assistUtils.getClass().getDeclaredMethod("getAssistComponentForUser", int.class);
            getAssistComponentForUserMethod.setAccessible(true);
            return (ComponentName) getAssistComponentForUserMethod.invoke(assistUtils, userId);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return null;
}

If you don't want to use reflection you can directly check the system settings:

public ComponentName getCurrentAssist(Context context) {
    final String setting = Settings.Secure.getString(context.getContentResolver(), "assistant");

    if (setting != null) {
        return ComponentName.unflattenFromString(setting);
    }

    return null;
}

It is the same setting that reads AssistUtils, but AssistUtils has also a fallback if the setting is not valid.



回答2:

Try this.

startActivity(new Intent(Intent.ACTION_VOICE_COMMAND).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));


回答3:

I try answer from Mattia Maestrini, it did work if returned component is an activity, like

ComponentInfo{com.sec.android.app.sbrowser/com.sec.android.app.sbrowser.SBrowserMainActivity}

but if the component is a service, I meet following problem

java.lang.SecurityException: Not allowed to start service Intent { 
act=android.intent.action.ASSIST cmp=com.google.android.googlequicksearchbox/com.google.android.voiceinteraction.GsaVoiceInteractionService launchParam=MultiScreenLaunchParams { mDisplayId=0 mBaseDisplayId=0 mFlags=0 } } without permission android.permission.BIND_VOICE_INTERACTION

and I do add

<uses-permission android:name="android.permission.BIND_VOICE_INTERACTION"/>

in Manifest file.

At last I use method in Activity.java

public boolean showAssist(Bundle args)

It's added from Android M and it could start assistant service successfully.