Android - Share resource between two applications - android

I have two applications, one works as a main app, and the another as a service.
In the service app manifest file, I configure a service like:
<service android:name=".services.FirstService">
<intent-filter>
<action android:name="ch.service.action.FIRST_SERVICE"/>
</intent-filter>
</service>
And in the main app, I start a service like:
Intent intent = new Intent("ch.service.action.FIRST_SERVICE");
startService(intent);
Here, I have to duplicate "ch.service.action.FIRST_SERVICE".
How can I avoid this?
How can I share some common constants, for example define one in service app, and can be retrieve in main app?
Any answer is appreciated.

You should use SharedPreference between both of your application. In your Service application you should write the String ch.service.action.FIRST_SERVICE to SharedPreference :
SharedPreference sharedPreferences = getSharedPreferences("any_name", Context.MODE_WORLD_READABLE);
SharedPreference.Editor mEditor = sharedPreferences.edit();
mEditor.putString("service_string","ch.service.action.FIRST_SERVICE");
mEditor.commit();
When you want to get the value from other application, you first need to get Context of your service application :
Context mServiceAppContext = createPackageContext("com.example.service_app_package", 0);
You can use mServiceAppContext to get the String value :
SharedPreference sharedPreferences = mServiceAppContext.getSharedPreferences("any_name", Context.MODE_WORLD_READABLE);
// Context.MODE_WORLD_READABLE is important, it makes the value readable across other applications
sharedPreferences.getString("service_string", /* default value */ "service_string","ch.service.action.FIRST_SERVICE");
Best Explaination is given at : http://thedevelopersinfo.com/2009/11/25/getting-sharedpreferences-from-other-application-in-android/

for something like this you have to create a library project and include it to both your main and service application and define your name in the library you included. Hope this helps, not sure if there is any other better way :)

If you can merge two applications together, certainly you can share anything you want. Actually one application can contains many service and intent service.
If you have some reason to separate one application into two, or they are two irrelevant apps, using intent to communicate always need class name which is unavoidable I think.

There are different ways to archive the same thing, but why not keep it simple:
Do you have a reference to the service project? if it so, why not just create a setting in the service project and reuse it on the main one when create the intent:
Intent intent = new Intent(cxt.getString("service_string", default value));
or, like I did in my apps, just create a public static final variable on the service class and access it from the main app?
public static final String ACTION_FIRST_SERVICE = "ch.service.action.FIRST_SERVICE";
If you don't have a reference to the service project and don't want to add, the best way is to expose it to anyone ... or create a lib project that both use

Related

How to redirect from own application another application?

I am creating my own app and at one point I want that user can go to any other application.So what will be the best code for that?
You can do that in many ways, but one of the common method is intents. You can create implicit intents for this purpose.
here is a sample code :
//From MainActivity.onCreate()
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("http://google.com"));
startActivity(intent);`
you can find further details about intents here.

Android: getting info on the calling app from activity

I want to implement a fine-granularity protection mechanism in an exported activity. The permissions framework does not seem to work for my requirements.
There are two options I am considering:
using Activity.getCallingPackage - only works if the activity is started with startActivityForResult - this is a limitation I would like to avoid if possible.
using Binder.getCallingUid - when called in an Activity, it returns the local UID, and not the calling UID.
Is there any way to allow activities started with startActivity to retrieve any information about the calling app?
You can add extra information in your intent.
Intent i = new Intent(this, NextClass.class);
i.putExtra("extra", "This is some extra information";
startActivity(i);
You retrieve the data from NextClass by:
Intent i = getIntent();
String extraStuff = i.getStringExtra("extra");
Is there any way to allow activities started with startActivity to retrieve any information about the calling app?
No, sorry, beyond your startActivityForResult() hack. Android's support for "a fine-granularity protection mechanism" is designed around services, not activities or other components.

Declare a service(to be private) in android

How would it be possible to create a private service? I mean my
custom service should not be accessible by other applications? What
parameters I should define in AndroidManifest.xml ?
Simply do not include an <intent-filter>. Then your service will only be accessible by components within your application. You would use an explicit Intent to interact with it (e.g., new Intent(this, MyPrivateService.class)).
As commonsware told that is a great answer.Also you can do in menifest also like this :
android:exported="false"

android: validate the identity of intent sender

I work in a company that produces several apps, not all those apps have the same signature or more like it we have at least 5-6 apps certificates for the time being.
We tried to create a mechanism in which all the companie's apps on the same device share the same is,
For example if user installed from the market App A and no app installed, a new ID will be generated, if now he installs App A, app B should have the same id as App A(id is just a generated UUID type #4) etc...
We are using broadcast at the moment and only apps with our permission can receive that broadcast and send back the id with another broadcast(explicit this time).
The broadcast and the responses are protected with our permission with signature level, this is of course not helping since we have more than one signature.
I tried to write an intent broadcast and recover that can have it's own mechanism of protection that will not be limited to only one signature but several, the problem is that things like Binder.getSenderUID() doesn't work for broadcasts and i get my own uid.
it looks like i have no way to get the identity of my snder unless he itself writes his id in the intent, which is NOT something i can trust as it can be easily faked.
Using encryption requires the apps to come with a key on them, which is not secured once more, turning to a server for validation takes too much time and on mobile not guaranteed to success since not 100% sure there is network around.
Anyone has any idea how can one get a validate\secure message from one app to another ?(all my apps but may have different signatures).
As always with a challenging question here i never get a proper, if ANY!' answer, so i'm forced to find it myself.
The problem with Intents is that it's not possible to get the sender as they are the parallel to mulicast in a network where there sender's address is not important.
If i wish to get the snder's UID i need to make a "remote" process even if he is local, instead of using broadcast IPC i need to use AIDL with IBInder implementation.
Once i have a Binder object i can call in my service getCallingUid() and get the uid of the caller, this will allow me to ask PackageManager to give me it's public certificate (without asking the process itself, i ask the OS) and compare it to a set of certificates i prepared in advance in the apk.
The calling application on the other side(the other process that sends me it's ID) just has to use the bindService(service, conn, flags) method to bind to me.
The disadvantage to this approach is ofcourse the time consuming process, Bind takes time, it's an async call that pass through the kernel and is not as fast as binding to a local service. Moreover since i might have several applications i need to synchronize the access my internal ID so only the first binding call that didn't fail will set and ID for me.
I still need to check if i can use the Messanger method that prevents the multi thread issues.
Hopes this helps someone else.
Sorry for late response...
Bind takes time, and more importantly, its asynchronous.
However, there is a way to make a synchronous bind - assuming of course the service you attempt to contact is already started at the time.
Android allowed for this more for BroadcastReceivers (which are async in nature, and thus can't use normal bindService) a BroadcastReceiver has a "peekService" method.
If you want to use it without listening to a broadcast, you can by doing:
final IBinder[] b = new IBinder[1];
new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
b[0] = peekService(context, intent);
}
}.onReceiver(context, intent);
IMyInterface i = IMyInterface.Stub.asInterface(b[0);
note that you don't bind to the service, so make sure to peek at on each use.
As already stated, binding is probably the best solution to this. However, you could consider switching to an Activity rather than a BroadcastReceiver then you can use getCallingActivity(), assuming you launched with startActivityForResult().
Declare you Activity as follows to make it "silent" like a BroadcastReceiver:
<activity
android:name=".FauxReceiver"
android:theme="#android:style/Theme.NoDisplay"
android:excludeFromRecents="true"
android:noHistory="true"
>
<intent-filter>
...
</intent-filter>
</activity>
Inspiration: How to get the sender of an Intent?
I was looking for a way to verify the package name of the application that sent the intent received by my intent-filter. That activity in my app that handles the intent-filter requires that the intent sender includes their process id in an Intent Extras field. My receiving activity can then get the associated application package name from the ActivityManager.
Here is some example code I found while shifting through StackOverflow.
Constants needed for both Apps
public static final String EXTRA_APP_ID;
public static final String ACTION_VERIFY = "com.example.receivingapp.action.VERIFY";
Calling Activity
Intent verifyIntent = new Intent();
verifyIntent.setAction(Consts.ACTION_VERIFY);
verifyIntent.putExtra(EXTRA_APP_ID, android.os.Process.myPid());
// Verify that the intent will resolve to an activity
if (verifyIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(verifyIntent, Consts.REQUEST_VERIFY);
} else {
Log.d(TAG, "Application not found.");
}
Receiving App
Manifest
<activity
android:name="com.example.receivingapp.ReceivingActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="com.example.receivingapp.VERIFY" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
ReceivingActivity
if (getIntent().hasExtra(OnyxCoreConsts.EXTRA_APP_ID)) {
string appName = null;
// Resolve intent
if (getIntent().getAction().equals(ACTION_VERIFY) {
int appPid = getIntent().getIntExtra(EXTRA_APP_ID, -1);
if (-1 != mAppPid) {
appName = Utils.getAppNameByPID(mContext, mAppPid);
}
if (null != appName && !"".equalsIgnoreCase(appName)) {
// Do something with the application package name
}
}
}
Utils class
public static String getAppNameByPID(Context context, int pid){
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {
if (processInfo.pid == pid) {
return processInfo.processName;
}
}
return "";
}

start a remote service and receive a result in Android

I have two applications.
One app has the Activity and another one is a background service.
I can able to access the service app from my activity app using implicit intent filters.
I need to receive a result from the service.
For ex:
From activity app, i am going to start the service and send a data.
In the service app, i need to receive the data and do some inspections and need to return to the activity app as modified result.
I can able to send by putExtra and can able to retrieve it in the service by getExtra. I need to return a value from service and receive it in activity app.
PS: The thing i needed is, the same way what we do with finish() and onActivityResult() with the Activity results.
Thanks in advance to you masters...
First add a class like this:
package com.test.context; //For example
public class MyContext extends Application
{
//Here you define the attributes to share through the application
// with setters and getters
}
and in the AndroidManifest.xml, add the path of the class,
in the example is com.test.context so:
<application android:name="com.test.context.MyContext"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name">
Then in your code you can do some like this:
MyContext ctx = (MyContext)getApplication();
And you will be able to share data in all the app, btw activities and services, i did it this way in a Tasker , and works fine.
Why do you want to communicate through intent while there is a perfectly working binder protocol.
http://developer.android.com/guide/topics/fundamentals/bound-services.html
If an activity starts a service with 'bindService()' then the service will run until the activity calls 'unbindService()'.

Categories

Resources