Enale and disable SEARCH_LONG_PRESS in Android applications - android

I want my application to be opened by long-pressing search button, but I want to add the option to deactivate this.
I added to my shortcutActivity this:
<intent-filter>
<action android:name="android.intent.action.SEARCH_LONG_PRESS"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
so when I long-press the search button it is opened, but now, I have to be able to turn this feature on.
This is not the main activity, this activity just calls to the main one and then finish().
How can I do this?
Thank you.

Unfortunently intent filters are static
An intent filter is an instance of the IntentFilter class. However, since the Android system must know about the capabilities of a component before it can launch that component, intent filters are generally not set up in Java code, but in the application's manifest file (AndroidManifest.xml) as elements. (The one exception would be filters for broadcast receivers that are registered dynamically by calling Context.registerReceiver(); they are directly created as IntentFilter objects.)
This is from the IntentFilter Documetation.

Actually, this is easily done using the PackageManager:
ComponentName cnShortcutActivity = new ComponentName("my.package", "my.package.ShortcutActivity");
getPackageManager().setComponentEnabledSetting(cnShortcutActivity, PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

Related

How to start an activity in an android Application from the Library

I have an Android application in Android Studio. And I've added a library into the application. The button, view, and activities are defined in the library. When I click on the button, I need to navigate to the activity defined in the application.
Usually, to navigate to another page, we used the intent, like this:
Intent intent = new Intent(MainActivity.this, Activity.class);
startActivity(intent);
But this is not a sufficient method to call the activity of the application from the library.
The problem is that the library and the application are independent; they have different packages. So the activity in the application cannot be recognized by the library.
How do I handle communication between the library and the application?
The normal way for doing this is to do this:
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.my.package","com.my.package.activity.ActivityName");
startActivity(intent);
This is an explicit reference to an activity within your library. You should ensure that when starting this Activity that you catch the ActivityNotFoundException as this can happen when the Activity does not exist in the system.
Ideally when building this Intent you should insure that you can resolve it by using PackageManager APIs.
However you should try to avoid hardcoding packages, but when it comes to a library, sometimes you don't have a choice.
Also one thing to note is that within the library you need to ensure that the Activity is exported so that you can access it outside of your application.
android:exported
Whether or not the activity can be launched by
components of other applications — "true" if it can be, and "false" if
not. If "false", the activity can be launched only by components of
the same application or applications with the same user ID. The
default value depends on whether the activity contains intent filters.
The absence of any filters means that the activity can be invoked only
by specifying its exact class name. This implies that the activity is
intended only for application-internal use (since others would not
know the class name). So in this case, the default value is "false".
On the other hand, the presence of at least one filter implies that
the activity is intended for external use, so the default value is
"true".
This attribute is not the only way to limit an activity's exposure to
other applications. You can also use a permission to limit the
external entities that can invoke the activity (see the permission
attribute).
Ref
http://developer.android.com/guide/topics/manifest/activity-element.html
Include the activity in AndroidManifest.xml.
To access an activity from any other project the easiest way is to
pass the whole class name (including package, e.g;
"com.myproject.MainActivitiy")
Calling from your library :
Intent intent= new Intent("com.myproject.MainActivitiy");
startActivity(intent);
And in your project manifest declare it like this
<activity
android:name="com.myproject.MainActivitiy"
android:label="#string/app_name" >
<intent-filter>
<action android:name="com.myproject.MainActivitiy" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
In this case, Intent can be used by providing the full class name including the package.
Let us suppose your current Activity class is MainActivity.java with package name com.app.myproject.
And you want to navigate to another Activity with class named Activity.java that is in another package com.app.external.
Include com.app.external.Activity.java in the manifest of your current project/library.
<activity
android:name="com.app.external.Activity"
android:label="#string/title_activity_login"
android:screenOrientation="portrait">
</activity>
And your Intent should be like this -
Intent intent = new Intent(MainActivity.this, com.app.external.Activity.class);
startActivity(intent);
In this case use Implicit Intent
Inside library Activity TESTActivity :
Intent intent = new Intent();
intent.setAction("com.myapp.myimplicit_action");
startActivity(intent);
and here is my manifest file declaration for some activity say 'ImplicitActivity' with the same action
<activity android:name=".ImplicitActivity">
<intent-filter>
<action android:name="com.myapp.myimplicit_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Custom intent to other app

I have a simple question but i can't find anything on google, maybe i use the wrong key word.
I'm developping an app with a service in background. This service is always started. I have a phone with a custom button than can start an app. But i want to use this button to start an action on my service don't start any activity.
To do that, i have think about an ugly solution : I configure my custom button to start an other app. This app is a blanck activity and on the onCreate() event i just send an itent to my service and after finish the activity.
My question is how can i send a custom intent to an other app ?
my idea : in the blanck activity write this
#Override
public void onCreate(){
super.onCreate();
Intent customIntent = new Intent("com.customIntent.action");
startActivity(customIntent);
finish();
}
On my service doing something like that :
IntentFilter it = new IntentFilter();
it.addAction("com.customIntent.action");
registerReceiver(myReceiver, it);
Thanks for your help !
You are registering receiver and it will only be catched when sendBroadCast will be called with the intent. Secondly, you are starting Activity with that Intent action. There is no Activity in xml/code which handles this action. Thirdly, you can add this Intent Filter in AndroidManifest against specific reciever and in Activity use
Intent customIntent = new Intent("com.customIntent.action");
LocalBroadcastManager.getInstance(this).sendBroadcast(customIntent);
AndroidManifest.xml
<receiver android:name="." >
<intent-filter>
<action android:name="com.customIntent.action" />
</intent-filter>
</receiver>
Hope this helps.
I dont't know if I understand your question correctly but this tutorial explains very well how you use an intent to interact with another app:
http://developer.android.com/training/basics/intents/index.html

Start Activity Using Custom Action

I am looking to start an activity in my app using a custom action. I have found a few answers but everything I try it throws java.lang.RuntimeException saying No Activity found to handle Intent { act=com.example.foo.bar.YOUR_ACTION }.
This is the activity in my manifest file:
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
</intent-filter>
</activity>
And this is how I'm starting the activity:
Intent intent = new Intent("com.example.foo.bar.YOUR_ACTION");
startActivity(intent);
Any help would be greatly appreciated.
I think what you need is to add a default category to your intent-filter,
eg.
<activity
android:name=".FeedbackActivity" >
<intent-filter>
<action android:name="com.example.foo.bar.YOUR_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
see this answer for more info.
I think you are creating your intent wrong. Try like this:
String CUSTOM_ACTION = "com.example.foo.bar.YOUR_ACTION";
//Intent i = new Intent(this, FeedBackActivity.class); // <--- You might need to do it this way.
Intent i = new Intent();
i.setAction(CUSTOM_ACTION);
startActivity(i);
Just add and intent-filter category as Default.
Implicit intent works perfectly and in many cases its better to use a implicit intent with Intent-action to call a service/Activity than using class-name.
Before startActivty() / startService() with proper context you cane use this method 'queryIntentActivities(Intent intent, int flags)' from package manager class.
It helps the ActivityManager (responsible for launching activities) to check whether the Android system is getting any match with you Intent.
If it doesn't it returns a list size 0 or else >0.
By this you can also check if your app is getting the call,and in this case even if your app is not installed / has got some problem, it will not crash but will throw a warning in Log. Users will face no big trouble apart from app not being launched.
(users will never forgive you if tour app crashes).
Hope this will help !!!
Happy Coding. :)
I faced the same problem when trying to launch the activity residing in the dynamic feature module and starting through action String as the Activity is not resolvable by name at compile time.
So I set the action but the activity crashes every time (No Activity found to handle intent bla bla.. ) until I set the correct package name.
Context c = getApplicationContext();// flag would be require Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag
Intent i = new Intent(action_string);
i.setPackage(context.getPackageName());//this did the trick actually
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
In the Manifest : add catrgory default to the intent filters
from google docs:
<category android:name="android.intent.category.DEFAULT"/>
Note: In order to receive implicit intents, you must include the CATEGORY_DEFAULT category in the intent filter. The methods startActivity() and startActivityForResult() treat all intents as if they declared the CATEGORY_DEFAULT category. If you do not declare it in your intent filter, no implicit intents will resolve to your activity.

interrupting link to my app

I have a problem. I'm using the below code to interrupt links to my app as
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="http" android:host="twitter.com"/>
<data android:scheme="http" android:host="facebook.com"/>
</intent-filter>
But the problem is that I need to set data scheme and host at runtime i.e. I can add or delete the host at runtime. How to set the value of data scheme and host at runtime? I am using below code but it is not working
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.VIEW");
filter.addCategory("android.intent.category.DEFAULT");
filter.addCategory("android.intent.category.BROWSABLE");
filter.addDataScheme("http");
filter.addDataAuthority("www.facebook.com", null);
RecieveBroadcaster receiver = new RecieveBroadcaster();
registerReceiver(receiver, filter);
Strictly speaking, the string corresponding to ACTION_VIEW is an activity action by convention; the fact that you place it into the intent-filter element of an activity in your manifest, makes it an activity action! The system listens for these on your application's behalf, which is basically why you don't (can't) listen for them yourself. The Context.startActivity() method generates these Intents.
The rules of intent resolution actually determine whether a particular Intent matches any IntentFilters. For activity intents, there may be multiple matches, and that usually displays the "Chooser" interface, so the user can select a target.
There are three Intent "streams" that never cross: startActivity(), sendBroadcast() and startService(). These are all initiated via methods in Context and each has a specific target Activity, BroadcastReceiver and Service respectively.
It is a simple matter to set up a BroadcastReceiver (not ReceiveBroadcaster did you even try that code?) to get the events you are interested in, and then use Context.startActivity() with the Intent you want. You can even use a custom action, so you know it was triggered by the receiver, and not the user.
The only question is: is there a broadcast event you can arrange to receive? There may be a system event you can register for, or you may be able to generate a custom event yourself, via Context.sendBroadcast().
Remember you can inspect the incoming Intent your activity was started with, and "forward" the same or a modified Intent if it doesn't exactly match what you are looking for. As you correctly determined, you cannot dynamically alter an activity's set of IntentFilters, so you will have to inspect the host of every request.
Remember you can also register receivers in your manifest as well, and have that implementation called automatically by the system.

Android: Understanding Intent-Filters

I would like to create an Intent-Filter, so that certain links will trigger the start of my application (see this stackoverflow-thread for example: How to register some URL namespace (myapp://app.start/) for accessing your program by calling a URL in browser in Android OS? )
While trying, I figured out, that I dont quite understand how Intents and Intent-Filters (defined in the Manifest.xml) actually work. What is the difference between the following:
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" />
or the following:
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MAIN" />
And what is actually the difference between category and action Intent-Filters. I read this page http://developer.android.com/reference/android/content/Intent.html but I still missing a basic understanding.
Instead of looking at it from your app's point of view, flip it around and look at it from the Intent side.
When an Intent is created, the creator has no idea what apps are on the system to handle that Intent. But the creator does know what it wants to do (e.g., an app might want to let the user pick out a contact from somewhere on the device), and needs to reach out to other apps on the system to ask for what's desired.
To do this, Intents have several pieces of information attached to them. Among them are actions and categories.
The actions define in a general way the action the Intent wants to do, like VIEW a contact, PICK an image from the Gallery, etc.
The category is an additional piece of information that gives the Intent another way to differentiate itself. For example, when a link in the browser is clicked, the Intent that is created has the BROWSABLE category attached to it.
So, when the OS resolves the Intent, it will look for registered Activities or BroadcastReceivers that have an intent filter that includes all of pieces of information. If the Intent specifies the PICK action, Activities that do not have an intent-filter with the PICK action will be discarded from the list of candidates to handle the Intent.
In this way, the combined set of action, categories, type, and (possibly) scheme associated with an Intent serve to pinpoint the set of Activities that can handle the Intent. When you set up your intent-filter in your manifest, you are telling the OS which class of Intents you can handle.
I had to examine the code of android.content.IntentFilter.matchCategories(Set<String> categories) to understand the matching of categories:
Successful match, if your IntentFilter has categories and the Intent doesn't provide Categories
Successful match, if your IntentFilter has all categories of the Intent. The filter also can have additional categories.
No match, if your IntentFilter has no categories and the Intent has categories
No match, if your IntentFilter has not the categories the Intent has
Especially #1 and #3 aren't obvious.

Categories

Resources