Difference between implicit and explicit intents [duplicate] - android

This question already has answers here:
What is the different between Explicit and implicit activity call in android?
(7 answers)
Closed 9 years ago.
I'm confused about the difference between implicit and explicit intents. What is the purpose of implicit and explicit intents, and why are these concepts used?
I am new to Android applications, so please provide some examples.

Implicit activity call
With an intent filter you create action for your activity so other apps can call your activity via an action:
<activity android:name=".BrowserActivitiy" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
.
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
startActivity(intent);
Explicit activity call
You make a call that indicates exactly which activity class to use:
Intent intent = new Intent(this, ActivityABC.class);
startActivity(intent);
Here's an additional reference

Explicit Intent: Explicit intent names the component.
Implicit Intent: Implicit Intents have not specified a component.
E.g: The java class which should be called Implicit intent asked the system to perform a service without telling the system which java class should do this service.

Related

Unable to start intent service via IMPLICIT intent

AndroidManifest.xml
<application android:name=".MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name"
>
<service android:name=".MyService"
android:exported="true">
<intent-filter>
<action android:name="android.service.myapp.MyService.actionA"/>
<action android:name="android.service.myapp.MyService.actionB"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
</application>
If I use the following code, my service is launched:
Intent intent = new Intent(context, MyService.class);
intent.setAction("android.service.myapp.MyService.actionA");
context.startService(intent);
But my service is not started if I launch it with this code:
Intent intent = new Intent("android.service.myapp.MyService.actionA");
context.startService(intent);
It is insecure to use an "implicit" Intent to start or bind with a Service. Starting with Lollipop, bindService() requires an explicit Intent (your first example where you specify the Context and Class for the Service.) The behavior of startService() is undefined for implicit Intents used to start a service. From the documentation on startService():
The Intent should contain either contain the complete class name of a specific service implementation to start or a specific package name to target. If the Intent is less specified, it log a warning about this and which of the multiple matching services it finds and uses will be undefined.
If you use the explicit form, you can completely remove the <intent-filter> from the manifest: it is not needed. If you need to specify some type of work to be done by the service via the Intent, consider using a extra within the Intent.

No Activity found to handle Intent (API Level 19)

For the life of me, I have been battling with this implicit intent for over 2 days now. I am trying to start an Activity implicitly using startActivity(intent) but I keep getting the "No activity found to handle intent", I have followed the directions on the android developer site on how to create and handle implicit intents and have scoured the web including a lot of posts on stackoverflow but the issue persists. Now time for some code:
Component A - Fires the implicit intent
Intent intent = new Intent();
//intent.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
intent.setAction(AppConstants.ACTION_VIEW_OUTLET);
//intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.withAppendedPath(OutletsContentProvider.CONTENT_URI,String.valueOf(outletID)));
intent.addCategory(Intent.CATEGORY_DEFAULT);
PackageManager pm = getPackageManager();
ComponentName cn = intent.resolveActivity(pm);
if(cn != null){
startActivity(intent);
Log.i(TAG, "Intent sent with action :" + intent.getAction());
Log.i(TAG, "Intent sent with data :" + intent.getDataString());
}
Android Manifest (within the same app as component A)
<activity
android:name=".OutletDetailsActivity"
android:label="#string/title_activity_outlet_details">
<intent-filter>
<data android:scheme="content" />
<action android:name="com.synkron.pushforshawarma.ACTION_VIEW_OUTLET" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
What could I be doing wrong? I have had a huge success using broadcast intents, but I don't want to use a broadcast/receiver in this case.
So I finally figured it out.
It just so happens that when data (URI, either by setData or by using the constructor that accepts the URI) is set on an intent, the system determines the appropriate MIME type required by the intent.
Intent intent = new Intent(AppConstants.ACTION_VIEW_OUTLET);
intent.putExtra("OUTLET_ID",
Uri.withAppendedPath(OutletsContentProvider.CONTENT_URI, String.valueOf(outletID)));
intent.addCategory(Intent.CATEGORY_DEFAULT);
When a URI or data is not set or specified, one is required to use settype() to specify the type of data (MIME) associated with the intent.
So basically, I didn't set the MIME type (I am required to since I set data (URI)) while initializing my intent. The intent-filter could not match the implicit intent because the data type test failed.
My work around, I passed my URI via the putExtra method leaving the data unset.
I also removed the reference to the data tag in the intent filter from the android manifest.
<activity
android:name=".OutletDetailsActivity"
android:label="#string/title_activity_outlet_details">
<intent-filter>
<action android:name="com.synkron.pushforshawarma.ACTION_VIEW_OUTLET" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

can not understand intent filter

I was reading intent & intent filter. i got the below code:
In activity:
Intent i = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
startActivity(i);
In Manifest:
<activity android:name="com.example.intentdemo.CustomActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="com.example.intentdemo.LAUNCH" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
</intent-filter>
</activity>
My question is that- am i not supposed to declare android.Intent.ACTION_VIEW , instead of android.content.Intent.ACTION_VIEW inside the intent?
android.content.Intent.ACTION_VIEW refers to the name of the constant ACTION_VIEW in the class android.content.Intent. The value of this constant is "android.intent.action.VIEW". Hence the difference.
If you see the source code of Intent class, ACTION_VIEW is a String constant whose value is "android.intent.action.VIEW"...
public static final String ACTION_VIEW = "android.intent.action.VIEW";
so both refers to the same value which is "android.intent.action.VIEW"...
You are getting confused in android.intent.action.VIEW and android.Intent.ACTION_VIEW. They both are totally different.
The way which you are using is IMPLICIT INTENT
These intents do not name a target and the field for the component name is left blank. Implicit intents are often used to activate components in other applications.
Intent i = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
startActivity(i);
ACTION
Intent object and is a string naming the action to be performed — or, in the case of broadcast intents, the action that took place and is being reported. The action largely determines how the rest of the intent object is structured . The Intent class defines a number of action constants corresponding to different intents. Check out list of Android Intent Standard Actions
The action in an Intent object can be set by the setAction() method and read by getAction().
Check More for Intent and Intent-Filter

Android service not starting with a warninig

I have a service that supposed to upload photos in the background. But when I try to start it, it doesn't start. In the logcat I've noticed that I get a warning Implicit intents with startService are not safe : Intent { .....}. I've already tripled checked that the action string is the same in the manifest and what I'm starting with. My code :manifest :
<service android:name=".photosupload.services.PhtosUploadService"
android:exported="false" android:process=":uploadPhotosServiceProcess">
<intent-filter>
<action android:name="com.yoovi.app.photosupload.services.action.START_UPLOAD" />
</intent-filter>
</service>
starting service code :
Intent i = new Intent(PhtosUploadService.ACTION_START_UPLOAD);
i.putExtra(PhtosUploadService.ALBUM_ID, albumID);
context.startService(i);
You need to understand implicit and explicit intents.
Explicit intent means you need to specify the exact class from which the intent will be serviced.
Your code should be similar to
Intent i = new Intent();
i.setClass(this, photosupload.services.PhtosUploadService.class);
If you want to send implicit intent to a service - Please Change to android:exported="true" in manifest.

Failing to start an activity with an implicit intent

I am a little confused why the implicit intent call is failing. When trying to start an intent I keep getting the following error:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content://org.chrisolsen.crossfit.providers.WorkoutProvider/workouts typ=vnd.android.cursor.dir/vnd.chrisolsen.crossfit.workout }
AndroidManifest
<activity android:name=".activities.WorkoutsActivity"
android:label="#string/title_workouts" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:mimeType="vnd.android.cursor.dir/vnd.chrisolsen.crossfit.workout"/>
</intent-filter>
</activity>
<provider
android:name=".providers.WorkoutProvider"
android:authorities="org.chrisolsen.crossfit.providers.WorkoutProvider" />
Calling activity (dashboard)
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(WorkoutProvider.CONTENT_URI, "vnd.android.cursor.dir/vnd.chrisolsen.crossfit.workout");
startActivity(intent);
Called activity (workouts). It doesn't make it here
Uri uri = getIntent().getData();
...
It seems like it should be simple, but I am confused to why it says there is no activity found.
Any ideas?
In order to be started with implicit intents, An activity must declare
<category android:name="android.intent.category.DEFAULT" />
Also, make sure you are using startActivity instead of sendBroadcast. There is a difference between these methods. A broadcast will not be received by an activity's intent filter. You must use a BroadcastReceiver for that.
Note that, although the Intent class is used for sending and receiving these broadcasts, the Intent broadcast mechanism here is completely separate from Intents that are used to start Activities with Context.startActivity(). There is no way for a BroadcastReceiver to see or capture Intents used with startActivity(); likewise, when you broadcast an Intent, you will never find or start an Activity. These two operations are semantically very different: starting an Activity with an Intent is a foreground operation that modifies what the user is currently interacting with; broadcasting an Intent is a background operation that the user is not normally aware of.
Source: http://developer.android.com/reference/android/content/BroadcastReceiver.html
Android docs: sendBroadcast
Android docs: startActivity

Categories

Resources