Android Tutorial [TUTORIAL] Inter-app Communication with Intents

tdocs2

Well-Known Member
Licensed User
Hi @tdocs2 ,

can you post your manifest editors?

Thanks
Hello, Federico.

The manifest for the IntentProvider is:
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.basic4ppc.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="11" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
AddActivityText(TestIntent, <intent-filter>
   <action android:name="swi.IntentProvider.REQUEST" />
   <category android:name="android.intent.category.DEFAULT" />
</intent-filter>)
'End of default text.
For the IntentRequester
B4X:
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: http://www.basic4ppc.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.
Best regards.

Sandy
 

Federico956

Member
Licensed User
Sure @tdocs2, I've done it!
Hi all,
I have a problem. I'm using a TC55 with its barcode scanner and its scanning app (DataWedge). In DataWedge there are some settings that allow you to use intent (Action, Category and delivery type), so when you scan a code you can have the code "into your app" and you can manipulate it.
I wrote a little code to try it and it works great, so I've tried to implement the code into my app and I noticed a strange behaviour: the first little app has only one activity and it works correctly, my app has lots of activity but I have to use the barcode scanner only in one of them.
When I scan a barcode, instead of execute the code written in Activity_Resume, it is called the activity create of the main activity.
I know it is something strange to explain, I hope you'll understand.

Here's the code of the Activity_Resume:

B4X:
Sub Activity_Resume
   Dim myintent As Intent
   myintent = Activity.GetStartingIntent
   If myintent.GetExtra("com.motorolasolutions.emdk.datawedge.data_string") <> Null Then
     Dim dwstring As String = "com.motorolasolutions.emdk.datawedge.data_string"
     Dim read As String = myintent.GetExtra(dwstring)
     EditBC.Text = read
   End If
End Sub
Thanks
 

thedesolatesoul

Expert
Licensed User
What device are you running on? It is possible the device runs low on memory and kills your app in the background, and then restarts it as the bar-code scanner exits.
 

thedesolatesoul

Expert
Licensed User
In your manifest, you need to add the intent filter to the activity you want to receive the intent.
Is it set correctly? You may have to post your manifest code if you cant spot it.
 

Federico956

Member
Licensed User
Here it is the manifest:

B4X:
AddManifestText(
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="14"/>
<supports-screens android:largeScreens="true"
  android:normalScreens="true"
  android:smallScreens="true"
  android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
AddActivityText(Main, <intent-filter>
  <action android:name="com.IntentProvider.REQUEST" />
  <category android:name="android.intent.category.DEFAULT" />
</intent-filter>)
It is the same in the small app I've tried and in my app.

EDIT: AddActivityText(Main, <intent-filter>
I have found the stupid but big error, I applied the intent-filter only to Main activity, right?
 
Last edited:

Federico956

Member
Licensed User
I've done it, now it works perfectly, thank you so much!
I've another (maybe the last :p) question: is there a way, in a Start Activity intent, to "abort" the intent after receiving data?
 

thedesolatesoul

Expert
Licensed User
I've done it, now it works perfectly, thank you so much!
I've another (maybe the last :p) question: is there a way, in a Start Activity intent, to "abort" the intent after receiving data?
After you took the data you can call Activity.Finish to shut down the current activity. This will though create a small flicker of your activity showing and disappearing. If you want to do it in the background, you can also use a Service for this.
 

imbault

Well-Known Member
Licensed User
DISCLAIMER:
This tutorial is written without testing code. There may be bugs, but try to understand the process, not copy the code.


An intent is a way for different applications to communicate at run time. It can be used to pass messages between activities and make them do actions. Using it with startActivity targets the intent to an activity. Broadcast intents are broadcast to all activities, and any applications with an intent filter can listen for it and perform an action.

Explicit Intents: The target component (service or activity) is known. (For e.g. an intent to the browser)

Implicit Intents: The system will determine which activity is best to launch this intent. (For e.g. Share intents)

More information on intents:
Intents and Intent Filters | Android Developers


In this example we have two apps.
- The Provider, that contains the data we need
- The Requester, that will request the data via Intent


Step 1: Setup the Provider to be able to receive intents
This can be done in two ways:
1. Explicitly setting the component, and making it visible by setting exported=true
2. Defining your own intent filter

We will do the second way since it is more structured.

We set up an intent filter to trigger our activity in the Provider.
In the manifest editor add the following, for the Activity you want to trigger.
You can also use a service (use AddServiceText instead)

B4X:
AddActivityText(Main, <intent-filter>
   <action android:name="com.maximussoft.myprovider.REQUEST" />
   <category android:name="android.intent.category.DEFAULT" />
</intent-filter>)
Step 2: Code the Provider to return the data
When using an Activity,

B4X:
Sub Activity_Resume
Dim in as Intent
in = Activity.GetStartingIntent
If in <> null Then
    If In.HasExtra("GetSettings") Then
       SendSettings(in)
       Activity.Finish
       Return
    End If
End If
End Sub
...so far so good...
however do you see the problem here?
no? come on think harder
How does the Providor know which app to send the data back to? The Intent by default has no information about the Calling package.

Again, there are two (simpler) ways to deal with this
1. Add information about the Requestor in the intent extras so we can call it back
2. Use StartActivityForResult. This allows you to get the calling package name, but infact you do not even need it. You can just return the result as an intent back to the Requestor Activity.

However, this is the point where you pause and think about what your apps need to do. Are they working silently in the background? Or do they show a dialog at some point?

For now, we go with the first option, and assume that the Requestor sends us an intent action in the extras.
So in SendSettings we do,
B4X:
Sub SendSettings(in as Intent)
   Dim returnIntent as Intent
   returnIntent.Initialize(in.GetExtra("Callback"),"")
   returnIntent.AddCategory("android.intent.category.DEFAULT")
   returnIntent.PutExtra("Settings",someGlobalSettings)
   returnIntent.PutExtra("Successful","True")
   StartActivity(returnIntent) 'Or StartService(returnIntent)
End Sub
Make note of how the return intent is initialized with the Callback field from the original recevied intent.

3. Set up the Requester
As you may have noticed, the Requester needs to be set up in the same way except for some minor differences. First you set up the manifest, with a different intent filter:
B4X:
 AddActivityText(Main, <intent-filter>
   <action android:name="com.maximussoft.myrequestor.CALLBACK" />
   <category android:name="android.intent.category.DEFAULT" />
</intent-filter>)
4. Code the Requester to request the data/settings
This can be anywhere in your code, but if its settings you want to request, it will probably be in activity create or resume. The thing to note here is how we initialiaze the intent with the ACTION of the PROVIDER. And we send the CallBack i.e. the intent of the REQUESTER as the CALLBACK so the provider can send us back the data.

B4X:
Sub RequestSettings
   Dim in as Intent
   in.Initialize("com.maximussoft.myprovider.REQUEST","")
   in.AddCategory("android.intent.category.DEFAULT")
   in.PutExtra("Callback","com.maximussoft.myrequestor.CALLBACK")
   in.PutExtra("GetSettings","True")
   StartActivity(in) 'Or StartService(returnIntent)
End Sub
5. Code the Requester to accept the data
Again this code is very similar to the Provider except that it gets the data
B4X:
 Sub Activity_Resume
Dim in as Intent
in = Activity.GetStartingIntent
If in <> null Then
    If In.HasExtra("Settings") Then
         AcceptSettings 'Do something here with your settings
    End If
End If
End Sub
Points to note:
While I dont consider intents to be very advanced, it can be quite overwhelming for newbies, so do your research.

There are many ways to do things and combinations of services/activities can make things complicated.

You can add permissions on your intent filters, this way Plugin apps need to have your permission in their manifest. This helps in *some* access control, mainly you can list all apps that can access your app/settings/data.
To see this in operation you can look at my apps that plugin to each other Cloudpipes and PhoneBackup.
If I get time I may write a sample otherwise not.
Thank you @thedesolatesoul ,

Very interesting, when you need APK communications, and I need a solution right now...

Just a simple question, does an App can be as well Provider and Requester?

Do we have others alternatives on Android (except file semaphores or SQLite solutions)?

Many thanks.

Patrick
 

johndb

Active Member
Licensed User
I'm using the information presented in this tutorial as a basis for my inter-app communications and it works very well with SDK 19 and below. Communicating with services using implicit intents fail in apps targeted for apps using SDK above 19 due to increased android security. How do I change the information in the tutorial to use explicit intents for service communications?

Thank you in advance.

[SOLVED]

To make the intent directed to a service "explicit" simply add the following:

Intent.SetComponent("<package name>/.<service>")


John
 
Last edited:

Rusty

Well-Known Member
Licensed User
Does anyone have a working simple example both provider and requestor?
Thanks,
Rusty
 
Top