9

In my activity I have a web view and in manifest.xml I have declared intent filter like this

 <activity
        android:name=".ui.socialNetwork.MySocialNetworkActivity"
        android:configChanges="orientation|screenSize"
        android:process=":fb"
        android:screenOrientation="portrait" >

    </activity>

    <activity-alias
        android:targetActivity=".ui.socialNetwork.MySocialNetworkActivity"
        android:name=".AliasMySocialNetworkActivity"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.PROCESS_TEXT" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity-alias>

This is not launcher activity. The intent filter used here is for copy paste toolbar on web view long press. This works fine. In addition to this I want to use Webview.setOnLongClickListener() for additional options, and I implemented like this.

webView = (WebView) findViewById(R.id.webview);

PackageManager pm = getApplicationContext().getPackageManager();
    ComponentName compName =
            new ComponentName(getPackageName(), getPackageName() + ".AliasMySocialNetworkActivity");
    pm.setComponentEnabledSetting(
            compName,
            PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

    webView.setOnLongClickListener(new View.OnLongClickListener() {
        public boolean onLongClick(View v) {
            WebView.HitTestResult hitResult = null;
            hitResult = webView.getHitTestResult();
            if (hitResult != null && hitResult.getExtra() != null) {
                final String hitRes = hitResult.getExtra();
                if (hitResult.getType() == WebView.HitTestResult.IMAGE_TYPE || hitResult.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
                    Intent ImageSaveIntent = new Intent(getApplicationContext(), SaveImage.class);
                    ImageSaveIntent.putExtra("putImage", hitRes);
                    startActivity(ImageSaveIntent);
                }
                if (hitResult.getType() != WebView.HitTestResult.IMAGE_TYPE || hitResult.getType() != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
                    PackageManager pm = getApplicationContext().getPackageManager();
                    ComponentName compName =
                            new ComponentName(getPackageName(), getPackageName() + ".AliasMySocialNetworkActivity");
                    pm.setComponentEnabledSetting(
                            compName,
                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                            PackageManager.DONT_KILL_APP);
                                       }
            }
            return true;
        }
    });

My problem is that

  1. If I use intent filter alone without webview.setOnLongClickListener(), I can copy paste the text in webview

  2. If I use webview.setOnLongClickListener() alone, I can do my additional options and it is working fine.

  3. If I implement both intent filter and webview.setOnLongClickListener(), I cannot copy paste the text from webview. webview.setOnLongClickListener() will work fine. Here I understood that both functionalities depends on longPress, But I want both to work together.

I searched Webview.HitResult options for TextType, but it is not having such option. https://developer.android.com/reference/android/webkit/WebView.HitTestResult.html

Cœur
  • 37,241
  • 25
  • 195
  • 267
Praveen Kumar
  • 225
  • 5
  • 18
  • Use touchlistener with gesture listener and return false in case you want to copy paste and return true if you want to do custom task – Mohammed Atif Nov 09 '16 at 11:10

4 Answers4

12

You can do this (disable the intent filter from android manifest programatically) by using Activity Alias:

1) add (e.g. AliasMySocialNetworkActivity) in AndroidManifest.xml to your MySocialNetworkActivity and move your intent-filter to them. It will be looks like that:

         <activity-alias
            android:targetActivity=".MySocialNetworkActivity"
            android:name=".AliasMySocialNetworkActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.PROCESS_TEXT" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
             </intent-filter>
        </activity-alias>

2) add this code to suppress intent-filter in alias activity when You need that

PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".AliasMySocialNetworkActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);

3) restore intent-filter, when You need it:

PackageManager pm = getApplicationContext().getPackageManager();
    ComponentName compName =
            new ComponentName(getPackageName(), getPackageName() + ".AliasMySocialNetworkActivity");
    pm.setComponentEnabledSetting(
            compName,
            PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
            PackageManager.DONT_KILL_APP);

For more details see this or that answer.

Update

Actually You don't need Alias, just use PackageManager.COMPONENT_ENABLED_STATE_DISABLED/PackageManager.COMPONENT_ENABLED_STATE_ENABLED

PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".MySocialNetworkActivity");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);

directly on your activity. Thanks @pskink.

Community
  • 1
  • 1
Andrii Omelchenko
  • 13,183
  • 12
  • 43
  • 79
2

This i achieved but faced issues when upgraded my app to Marshmallow support.

Dynamically you can't remove the IntentFilter from the Manifest Components.

If you are working on Marmalade/Native languages like C & C++(NDK), You can achieve disable the IntentFilter components but after platform upgrade(like Kitkat to LollyPop) it gives problem.

This changes is not recommended by android community in any of the developer.android.com pages.

One Solution could be,

  String packageName = getPackageName();
    try {
        PackageInfo p = getApplicationContext().getPackageManager().getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
        for (ActivityInfo activityInfo : p.activities) {
            if(log.d()) log.d("ACT " + activityInfo.name+" "+activityInfo.packageName);
        }
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
    }

Go with alias from the code "alias"

ComponentName componentWithoutTextFiles = new ComponentName(packageName, packageName".alias");

Takermania
  • 1,345
  • 2
  • 12
  • 20
2

In my case,

Code in AndroidManifest.xml

<activity-alias
        android:name="alias.Shortcut"
        android:icon="@drawable/shortcut_icon"
        android:label="@string/shortcut_text"
        android:targetActivity="com.myexample.shortcutexample.ShortcutActivity">
        <intent-filter>
            <action android:name="android.intent.action.CREATE_SHORTCUT" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity-alias>

Code to disable alias

PackageManager pm = getApplicationContext().getPackageManager();
        ComponentName compName =
                new ComponentName(getPackageName(), getPackageName() + ".alias.Shortcut");
        pm.setComponentEnabledSetting(
                compName,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);

when I tried

getPackageName() + ".alias.Shortcut"

I got java.lang.IllegalArgumentException: Component class com.myexample.shortcutexample.alias.Shortcut does not exist in com.myexample.shortcutexample

So I changed my code to

ComponentName compName =
                new ComponentName(getPackageName(), "alias.Shortcut");

and it worked like charm.

Abhinav Dua
  • 63
  • 3
  • 10
  • Would this strategy work as well for enabling/disabling a `meta-data` tag in the Manifest? For instance, a web browser app implementing `WebView` that offers users the ability to [opt-in/out of Google metrics collection](https://developer.android.com/guide/webapps/managing-webview#metrics). – AdamHurwitz Dec 06 '20 at 18:42
1

Answer from @Andrii Omelchenko is correct, but I'd like to add that if you use applicationIdSuffix parameter in build.gradle for your build type (e.g. ".debug" suffix for debug variant) or build flavor, it won't work as it won't find your component in code.

Problem is that when you specify:

<activity-alias
    android:targetActivity=".MySocialNetworkActivity"
    android:name=".AliasMySocialNetworkActivity" />

See the dot "." at the start of the name - Android will prepend this with the package name of your app, without the applicationIdSuffix, so you will get e.g. com.example.packagename, but in code, context.getPackageName() will return package name with the applicationIdSuffix! So it won't find the component in that case.

There are two solutions:

  • Specify full android:name, without the "." at the start. E.g. "MySocialNetworkActivity".
  • Specify the packagename prefix with the variable "${applicationId} which contains the applied applicationIdSuffix (it is automatically available in manifest file):

    <activity-alias
        android:targetActivity=".MySocialNetworkActivity"
        android:name="${applicationId}.AliasMySocialNetworkActivity" />
    
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Robyer
  • 4,632
  • 2
  • 23
  • 21