AIDL interface between two applications - android

I've stuck a total wall with the AIDL interfacing. I've an app which has to be controlled via 3rd party application (I've enough control over this so I can ask them to implement what ever I need into their activity)
Originally my app was also an activity with interface and everything but I've changed it to be a background service and for testing, I created a dummy app which manages to start the service app to the background.
Now I would like a way to request method calls from the service (mainly; start, stop, sendData). I've created the .aidl files for both apps. The aidl file implements only one method (this is courtesy of some other question here.)
package foo.testapp;
interface IScript
{
String executeScript(String script);
}
while the other aidl is same except the package is "foo.otherapp". The implementations I've found online had same package for both aidl files, but for me this causes an error (guess this is just a problem on my part since I hate namespaces and packages so I often just name them badly, if it's important to change them, I can do it)
The plan was to use this method to send a string to the service and just have a switch over predefined strings to call a correct method ( could also just implement three different methods if it improves the usage).
Anyway... I can't get the aidl to connect, I get error "Unable to start service intent
{act=foo.testapp.IScript } : not found
I would this guess has something to do with my misunderstandings ie. packagenames or so)
this is the implementation in my test activity app
private final IScript.Stub mBinder = new IScript.Stub()
{
#Override
public String executeScript(String script) throws RemoteException
{
// TODO Auto-generated method stub
}
};
IScript mService = null;
private ServiceConnection mConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
mService = IScript.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName className)
{
mService = null;
}
};
Then in OnCreate() method I'll do this:
bindService(new Intent(IScript.class.getName()),
mConnection, Context.BIND_AUTO_CREATE);
In service class I have this;
#Override
public IBinder onBind(Intent intent)
{
// Select the interface to return. If your service only implements
// a single interface, you can just return it here without checking
// the Intent.
if (IScript.class.getName().equals(intent.getAction()))
{
return mBinder;
}
return null;
}
/**
* The IRemoteInterface is defined through IDL
*/
private final IScript.Stub mBinder = new IScript.Stub()
{
#Override
public String executeScript(String script) throws RemoteException
{
if (script == "test")
{
return "foo";
}
return "fail";
}
};
And finally the manifest files;
well actually, I've no idea if I have to add something into manifest files when dealing with the aidl. In the one example I saw this;
<intent-filter>
<action android:name="foo.otherapp.IScript" />
</intent-filter>
and
<intent-filter>
<action android:name="foo.testapp.IScript" />
</intent-filter>
I would guess that the errors could be anywhere. I've been trying to set this up with chewing gum and band-aids. Guess I've just misunderstood some basic concept of this.
Anyway, any help is welcome.
Thanks in advance!

I decided to answer my own question since I found an exact solution.
My Life With Android
Everything worked just by copy pasting the source and changing the package names and function names correctly (assuming you're implementing this into your own project)
Source from client folder goes to the client activity and serviceimpl goes to service. I didn't need the 'Service activity', so I left it out ( and it doesn't really seem to be invoked anyway).
I don't have enough reputation to post multiple links, so you can get the source from the top of the page.
"Update: please check out the updated example program for Android SDK 1.5."

I struggled with this too. You are correct in your guess that the RemoteInterface.aidl needs to have the same package name in both the service and the test app - so where do you put it!?
If you are developing in Eclipse then the trick is to have a common source folder (common to both projects) Make this folder outside of both projects and in the build properties/source, click 'link source' and browse to the location of the common source. (You can call it any name you want) Do this in both projects and put the interface.aidl in there. It will appear in both projects' Package Explorer and when you change it in one project, the other will get updated too.
In the common source folder I put the interface.aidl in a package with the same name as the service.
If you are using Ant to build, the it gets a bit tricky as the default ant_rules.xml doesn't support two aidl folders, and you'll have to modify your build.xml quite a bit add a new target and all its dependencies.
I got my project going by adapting the samples form Chapter 17 from the 'download source' here:
link text

Related

How to call custom aosp service from android app

I am working on a project which runs on aosp. I added a system service to aosp. I run this service with using adb shell "service call" command successfully. While creating service, I applied following ways.
Added an aidl file
Added a .java file which derived from aidl
Added jni file.
After creating service, I wrote an basic android app. I want to call this service from this android app. How I can call this service from android app.
Create a service manager in: frameworks/base/core/java/android/os/MySerManager.java next to the .aidl interface definition.
In frameworks/base/core/java/android/content/Context.java
search for a simple service like VIBRATOR_SERVICE and add MYSER_SERIVCE to every occurrence.
In particular add: public static final String MYSER_SERVICE = "myser";
Do the same in frameworks/base/core/java/android/app/SystemServiceRegistry.java
making sure to add:
import android.os.MySerManager;
registerService(Context.MYSER_SERVICE, MySerManager.class,
new CachedServiceFetcher<MySerManager>() {
#Override
public MySerManager createService(ContextImpl ctx) {
return new MySerManager();
}});
This service manager can be used outside of the AOSP by building the sdk: https://android.googlesource.com/platform/sdk/+/master/docs/howto_build_SDK.txt
And within the AOSP by getting the system service from the Context:
MySerManager mySerManager = (MySerManager)getSystemService(Context.MYSER_SERVICE);
I managed to solve how system service calls from android app. After compiling aosp, classes.jar in framework_intermediates file is created to out/target/common/obj/JAVA_LIBRARIES. I added classes.jar to my android app and I used following codes.
IBinder binder = ServiceManager.getService("my_service");
IMyService myService = IMyService.Stub.asInterface(binder);
int result = myService.myFunction();

Why are references to the in-app billing classes not recognized by Ecliplse?

I am using this tutorial to implement in-app billing for an Android app. When I get to the section titled "Binding to IInAppBillingService" they provide a snippet like this:
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
mService = null;
}
#Override
public void onServiceConnected(ComponentName name,
IBinder service) {
mService = IInAppBillingService.Stub.asInterface(service);
}
};
And even though I installed the in-app billing library from my SDK manager, it doesn't seem to be recognizing the classes used in this snippet.
Am I maybe using a tutorial that isn't the most clear? Is there a better tutorial? This one seems to gloss over a few important details like where to get the actual class implementation for the referenced classes in that code.
Or do I just not have the libraries correctly configured?
Thank you!
Make sure you've copied <sdk>/extras/google/play_billing/IInAppBillingService.aidl file to your Eclipse project's src/com/android/vending/billing package. Then rebuild the project. Once you've done this, Eclipse will generate IInAppBillingService.java class and put it into gen folder of your project. Don't forget to import that java class and everything must compile.

make getSystemService() recognize our new system service

I'm using the book "Embedded Android".
I'm making a new System Service using AOSP(4.0.3_r1).
I want my system service to be registered in frameworks/base/core/java/android/content/app/ContextImpl.java so that I can use it through getSystemService() method.
The problem is, I can't find the app folder under content:androidroot/frameworks/base/core/java/android/content/app/ContextImpl.java
But, I found it in:androidroot/frameworks/base/core/java/android/app/ContextImpl.java
Are these 2 files the same? or is it just missing(the content/app folder)?
Any idea on what to do?
Karim wrote his book mostly orienting on Android 2.3.4 version. Something can be changed from this time. This is an example what has been changed.
Are these 2 files the same? or is it just missing(the content/app folder)?
These are the same files.
Any idea on what to do?
As I said the implementation has been changed. I looked into the code and here what you can change to make your code working (I can only suppose because I did not actually build my code). In the static block of ContextImpl class you need to add the following code:
registerService(ACCOUNT_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(OPERSYS_SERVICE);
IOpersysService service = IOpersysService.Stub.asInterface(b);
return new OpersysManager(service);
}});
You need to use SystemServer which holds all system services' names.
You should check this link out:
http://processors.wiki.ti.com/index.php/Android-Adding_SystemService

Android inapp billing - BillingService has compile errors with onServiceConnected and onServiceDisconnected

I am using the Dungeons application example and I am using the BillingService class provided in that example.
I am using Java 6 and #override works for me, but I get a compile error on these two methods inside BillingService.java:
/**
* This is called when we are connected to the MarketBillingService.
* This runs in the main UI thread.
*/
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (Consts.DEBUG) {
Log.d(TAG, "Billing service connected");
}
mService = IMarketBillingService.Stub.asInterface(service);
runPendingRequests();
}
/**
* This is called when we are disconnected from the MarketBillingService.
*/
#Override
public void onServiceDisconnected(ComponentName name) {
Log.w(TAG, "Billing service disconnected");
mService = null;
}
Would someone help me understand why this is happening?
Thanks!
Make sure your class implements the ServiceConnection interface.
In App billing is a challenge to get started with. The trick is to get it started in a independent project and then do all your specific feature. Trust me on this, and done be brave and do it all together, its not worth the time it takes to get started. I hope google improves on in app billing overall, to make it easy to implement, understand and debug. I had blogged about it a while back and created a helloworld kinda project for people to download and get working. I hope it helps you too.
Debug Android inapp billing using Eclipse
I think you should simply remove the #Override decorator from both methods. I'm using the Google BillingService class and this is my method:
public void onServiceConnected(ComponentName name, IBinder service)
{
mService = IMarketBillingService.Stub.asInterface(service);
runPendingRequests();
}
You are implementing an interface, not extending a class with abstract methods.
You might try to use default compile options.
Right-click (or Control-Click) the project and select "Properties"
Select "Java Compiler"
Uncheck "Enable Project Specific Settings"
Eclipse will prompt to re-compile and it should be all good.
Install your app Signed ...so go to android tools export signed application .... now that its signed you can get back queries. This was my issue at least on a physical device.
Right click on the Project
Select --> Android Tools
Select --> Fix Project Properties
This fixed it for me (I believe it was a Java compiler setting throwing it off).

LVL licensing in a Live Wallpaper?

Has anybody had success integrating the Licensing Verification Library (LVL) with a Live Wallpaper? If it were just running an Activity, it'd be crystal clear to just extend my Activity from the Licensing Activity, which in turn extends Activity. But Live Wallpapers are a Service, and I'm not sure how the two are intended to interact.
I'm using code derived from this: http://www.droidforums.net/forum/android-app-developers/69899-market-license-easy-implementation-protect-your-apps.html which seems to be the code that nearly everything I can find on the web refers to.
I notice that wallpaper settings are an activity, and I have those working properly, but for some reason I can't grok the Licensing stuff...
It's actually really quite simple, you don't need to use any Activity class to implement licensing into a WallpaperService.
Make sure you've followed the directions carefully at http://developer.android.com/guide/publishing/licensing.html
Here's how I did it:
Your extended Engine class should include something similar to the following... (code not essential to your question has been removed)
class startYourEngines extends Engine {
public startYourEngines() {
super();
licenseStatus(); //custom license check method (for modularity)
//the rest of your engine would go here
}
public void onDestroy() {
super.onDestroy();
licenseChecker.onDestroy(); //we call this to close IPC connections
}
//prep work
private static final String BASE64_PUBLIC_KEY = //OMITTED//;
private LicenseCheckerCallback licenseCallback;
private LicenseChecker licenseChecker;
private byte[] salt = "rAnd0mStr!ng".getBytes();
private AESObfuscator aes;
private String deviceId;
//our custom license check method
private void licenseStatus() {
deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
aes = new AESObfuscator(salt, getPackageName(), deviceId);
licenseCallback = new licenseVerification();
licenseChecker = new LicenseChecker(context, new ServerManagedPolicy(context, aes), BASE64_PUBLIC_KEY);
licenseChecker.checkAccess(licenseCallback);
}
//our callback method
private class licenseVerification implements LicenseCheckerCallback {
#Override
public void allow() {
//allow full app use
}
#Override
public void dontAllow() {
//prevent or limit app use
}
#Override
public void applicationError(ApplicationErrorCode errorCode) {
//error handling here
}
}
}
Licensing on the Android platform was created with versatility in mind. Just be sure to read through the documentation, and you shouldn't have any issues.
I have only written applications that start activities, but looking at my source code, it seems that the only reason that you would have to have an Activity do the license check is to show dialogs.
In all of the examples available on line, the LicenseCheckerCallback implementation always shows a dialog in the allow() and dontAllow() methods. Why not just show a toast in dontAllow() and exit your wallpaper service (call stopSelf(YourService.this))?
Let me know if you want more information, because I dont think you are limited to only using an activity for license checking. As an aside, make sure that you dont keep whole strings, etc in your app or in the preferences. Anyone with root access can access your preferences and if your app is decompiled, your strings are visible...
I think I've actually got it working now. I'm extending LicenseCheckActivity to my own Activity class that I'm calling in the manifest file with the usual MAIN action and LAUNCH category. I instantiate my class, do the license check, and then either allow the wallpaper to function or not based on that result (though the best way to do that is still something I need to sort out).
It almost seems too easy that I think I must be missing something. I'd appreciate anybody with experience with selling a licensed live wallpaper on the Android Market to share whatever wisdom they care to.

Categories

Resources