Bind to AIDL remote service on Android - android

I have an Android app that specifies two AIDL files and a service. This service should be used from another app to invoke the methods defined on the AIDL. I have followed the Android Documentation on AIDL to implement the AIDL files and the service (see the code below).
Then I created a very simple client app (also shown below) to bind to the service and invoke the method defined on my AIDL file. However, the bindService always returns false and mentions that the intent cannot be found. These are some things I tried to correctly reference the intent on the client side:
Intent intent = new Intent("a.b.c.service");
intent.setPackage("a.b.c");
---
Intent intent = new Intent("service");
intent.setPackage("a.b.c");
---
Intent intent = new Intent();
intent.setClassName("a.b.c", "a.b.c.services.MyService");
---
Intent intent = new Intent();
intent.setClassName("a.b.c.services", "a.b.c.services.MyService");
---
Intent intent = new Intent();
intent.setClassName("a.b.c", ".services.MyService");
---
Intent intent = new Intent();
intent.setAction("service");
intent.setPackage("a.b.c");
intent.setClassName("a.b.c", ".services.MyService");
---
Intent intent = new Intent();
intent.setAction("service");
intent.setClassName("a.b.c", ".services.MyService");
If I try from the same application where the service resides, I can use the following and it will work:
Intent intent = new Intent(this, MyService.class);
But since this is a remote service, I do not have access to MyService class from the client app, so I can't find any way of making it work.
I have wondered through a lot of StackOverflow posts without any luck. Examples:
Android: Binding to a remote service
How can I use AIDL remote service to deal with defferent clients' concurrent requests?
Android Bind Service returns false every time
How should I specify my intent in this case?
Thanks in advance.
Relevant code:
IServiceInterface.aidl
package a.b.c;
import a.b.c.IServiceInterfaceGetStuffCallback;
interface IServiceInterface
{
void getStuff(String arg1, IServiceInterfaceGetStuffCallback callback);
}
IServiceInterfaceGetStuffCallback
package a.b.c;
interface IServiceInterfaceGetStuffCallback
{
void onGetStuffResponse(String arg1, boolean arg2, int arg3, int arg4);
}
a.b.c./services/MyService.java
public class MyService extends Service
{
private final MyService self = this;
private MyServiceHandler handler = null;
private final HandlerThread handlerThread = new HandlerThread("AidlServiceThread");
//Callbacks
private final ArrayList<IServiceInterfaceGetStuffCallback> getStuffCallbacks = new ArrayList<>();
private final int MY_SERVICE_GET_STUFF_MSG = 1;
public MyService()
{
}
#Override
public IBinder onBind(Intent intent)
{
// Handler Thread handling all callback methods
handlerThread.start();
handler = new MyServiceHandler(handlerThread.getLooper());
return mBinder;
}
IServiceInterface.Stub mBinder = new IServiceInterface.Stub()
{
#Override
public void getStuff(String arg1, IServiceInterfaceGetStuffCallback callback) throws RemoteException
{
//Register the callback internally
getStuffCallbacks.add(callback);
final int cbIndex = getStuffCallbacks.size() - 1;
getStuff((arg1, arg2, arg3, arg4) ->
{
MyServiceResponse response = new MyServiceResponse();
response.arg1 = arg1;
response.arg2 = arg2;
response.arg3 = arg3;
response.arg4 = arg4;
Message message = handler.obtainMessage();
message.arg1 = cbIndex;
message.obj = response;
message.what = MY_SERVICE_GET_STUFF_MSG;
handler.sendMessage(message);
});
}
};
private class MyServiceHandler extends Handler
{
int callbackIndex = 0;
MyServiceHandler (Looper looper)
{
super(looper);
}
#Override
public void handleMessage(Message msg)
{
callbackIndex = msg.arg1;
MyServiceHandler response = (MyServiceHandler)msg.obj;
switch (msg.what)
{
case MY_SERVICE_GET_STUFF_MSG:
{
try
{
getStuffCallbacks.get(callbackIndex).onGetStuffResponse(response.arg1, response.arg2, response.arg3, response.arg4);
}
catch (RemoteException e)
{
e.printStackTrace();
}
break;
}
default:
break;
}
}
}
private static class MyServiceResponse
{
public String arg1;
public boolean arg2;
public int arg3;
public int arg4;
}
}
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="a.b.c">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<permission
android:name="a.b.c.myservice"
android:protectionLevel="signature" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|keyboard|colorMode|density|navigation|fontScale|layoutDirection|locale|mcc|mnc|smallestScreenSize|touchscreen|uiMode">
(...)
<service
android:name="a.b.c.services.MyService"
android:enabled="true"
android:exported="true"
android:permission="a.b.c.myservice">
<intent-filter>
<action android:name="a.b.c.myservice" />
</intent-filter>
</service>
</application>
</manifest>
Client app - MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener
{
private final String TAG = "aidltest";
MainActivity self = this;
IServiceInterface service = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_get_stuff).setOnClickListener(this);
}
#Override
public void onClick(View view)
{
if (view.getId() == R.id.btn_get_stuff)
getStuff();
}
void getStuff()
{
Log.e(TAG, "getStuff invoked");
Intent intent = new Intent("a.b.c.myservice");
intent.setPackage("a.b.c");
boolean res = getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.e(TAG, "Service binding result: " + res);
}
private ServiceConnection serviceConnection = new ServiceConnection()
{
public void onServiceConnected(ComponentName className, IBinder service)
{
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
self.service = IServiceInterface.Stub.asInterface(service);
Log.e(TAG, "ServiceInterface attached");
}
public void onServiceDisconnected(ComponentName className)
{
service = null;
Log.e(TAG, "Service disconnected");
}
};
}

The following changes work for me:
Adjust your manifest as follows:
<service
android:name="a.b.c.services.MyService"
android:enabled="true"
android:exported="true"
android:permission="a.b.c.myservice">
<intent-filter>
<action android:name="a.b.c.myservice" />
<category android:name="android.intent.category.DEFAULT"/> <---- NEW LINE
</intent-filter>
</service>
Run adb shell pm list packages and get the package id of the apk where you declared the service. This is needed for building the intent in step 3. Let's call it PACKAGE_ID.
Adjust the getStuff method as follows:
void getStuff() {
Log.e(TAG, "getStuff invoked");
Intent intent = new Intent("a.b.c.myservice"); // This is the value you used in the action for your service as declared in the manifest.
intent.setPackage(PACKAGE_ID); // This is the value you retrieved in step 2.
boolean res = getApplicationContext().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Log.e(TAG, "Service binding result: " + res);
}

Related

Unable to launch app when removed from recent apps when foreground service is running Android

I have implemented a foreground service with a notification for my existing android project.
Problem: I remove the app from the "recent app" when the foreground service is running and its notification is visible. Later, I try to launch the app by clicking on the app icon. A black screen appears for a second and the app is not launched.
The app is stuck in this state until I got to app settings and force close the application.
Foreground Service:
public class FileSyncService extends Service {
private static final int FILE_SYNC_SERVICE_ID = 901;
public static final String FILE_SYNC_SERVICE_ACTION_STOP = "StopFileSyncService";
public static final String FILE_SYNC_SERVICE_ACTION_START = "StartFileSyncService";
#Inject
private FilePushManager filePushManager;
#Inject
private NotificationController notificationController;
#Override
public void onCreate() {
super.onCreate();
Logger.d("[FileSyncService][onCreate]");
BootstrappingManager.getInstance().getInjector().injectMembers(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Logger.d("[FileSyncService][onStartCommand]");
if (intent != null && intent.getAction() != null && intent.getAction().equals(FILE_SYNC_SERVICE_ACTION_STOP)) {
Logger.d("[FileSyncService][onStartCommand] stopSelf");
stopForegroundService();
} else {
Logger.d("[FileSyncService][onStartCommand] startForeground");
startForeground(FILE_SYNC_SERVICE_ID, notificationController.createFileSyncNotification());
filePushManager.startFilePush();
}
return START_STICKY;
}
#Override
public void onDestroy() {
Logger.d("[FileSyncService] onDestroy");
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
private void stopForegroundService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
stopForeground(STOP_FOREGROUND_REMOVE);
} else {
stopForeground(true);
}
stopSelf();
}
}
Methods to start stop service:
public static void startFileSyncService(Context context) {
Intent serviceIntent = new Intent(context, FileSyncService.class);
serviceIntent.setAction(FileSyncService.FILE_SYNC_SERVICE_ACTION_START);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Logger.d("[MandatoryUtils][startFileSyncService] foreground");
try {
context.startForegroundService(serviceIntent);
} catch (SecurityException e) {
Logger.e("[MandatoryUtils][startFileSyncService] unable to start File Sync Service", e);
} catch (Exception e) {
Logger.e("[MandatoryUtils][startFileSyncService] unable to start File Sync Service Exception", e);
}
} else {
Logger.d("[MandatoryUtils][startFileSyncService] ");
context.startService(serviceIntent);
}
}
public static void stopFileSyncService(Context context) {
Logger.d("[MandatoryUtils][stopFileSyncService]");
Intent serviceIntent = new Intent(context, FileSyncService.class);
serviceIntent.setAction(FileSyncService.FILE_SYNC_SERVICE_ACTION_STOP);
context.startService(serviceIntent);
}
Launcher Activity:
<application
android:name="net.activities.MainApplication"
android:allowBackup="false"
android:icon="#drawable/scl"
android:label="#string/app_name"
android:manageSpaceActivity="net.activities.SplashActivity"
android:networkSecurityConfig="#xml/network_security_config"
android:resizeableActivity="false"
android:theme="#style/ContentLibraryTheme"
tools:replace="allowBackup, android:theme">
<uses-library android:name="org.apache.http.legacy" android:required="false" />
<activity
android:name="net.activities.SplashActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
android:theme="#style/Theme.App.Splash"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
...

How to start a service even when the app is not open

Here I am creating a chat app. In this app I want to load data from firebase realtime database whenever user switch on his internet or connects his phone to wifi no matter whether the app is open or not. I am doing this using service and broadcast. But I don't know why its not working. The method of fetching data is working properly as I have checked it in another activity. Kindly checkout my codes below
I have registered my broadcast and service in menifest file as
<service android:name=".broadcasts.receiveMsgService" android:exported="true"/>
<receiver android:name=".broadcasts.receiveChattersBroadcast"
android:exported="true"
android:enabled="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
My broadcast file
public class receiveChattersBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Check the action of the intent
String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED) ||
action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
// Start the background service
Intent serviceIntent = new Intent(context, receiveMsgService.class);
context.startService(serviceIntent);
}
}
}
My service file
public class receiveMsgService extends Service {
private static final String LOG_TAG = "MyForegroundService";
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(LOG_TAG, "onStartCommand");
// Load the messages from Firebase
loadMessagesFromFirebase();
return START_STICKY;
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void loadMessagesFromFirebase(){
FirebaseDatabase database;
DatabaseReference refernec;
// chatrecycler = view.findViewById(R.id.fragAllChatRecycler);
database = FirebaseDatabase.getInstance();
refernec = FirebaseDatabase.getInstance().getReference();
refernec.keepSynced(true);
ArrayList<chatterModal2> modals = new ArrayList();
SharedPreferencelogin session = new SharedPreferencelogin(getApplicationContext());
String userFireId = session.getFireId();
databaseHelper db = new databaseHelper(getApplicationContext());
database.getReference().child("chatters").addValueEventListener(new
ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.exists()){
for (DataSnapshot snapshot1:snapshot.getChildren()){
chatterModal2 modal = snapshot1.getValue(chatterModal2.class) ;
String receiverId = modal.getRecieverId();
String sender = modal.getSenderId();
if(receiverId.trim().equals(userFireId) ||
sender.equals(userFireId)) {
modals.add(modal);
String addResult = db.addChatter(modal.getRecieverId(),
modal.getSenderId(), modal.getMsg(), modal.getUnseen(), modal.getProId(),
String.valueOf(modal.getTime()));
}else{
//do nothing
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
I have not mentioned this service and broadcast any where else. Do I have to mention it or call it in any activity? Please tell me what's wrong

FileObserver does not triggering events while invoking in background service

There are answered questions regarding FileObserver in Android and I am following them but still my code doesn't work. Here I am posting my code, I am trying to set fileObserver via service so it work even if the app itself is closed. When running, it is invoking the DirectoryObserver Constructor but adding or deleting a file doesn't invoke the event
public class MainActivity extends AppCompatActivity
{
private String sharedPreferencesKey = "IsThisFIrstTime";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!preferences.contains(sharedPreferencesKey)) {
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(sharedPreferencesKey, false);
editor.apply();
try {
startTheServices();
}
catch (Exception ex) {
}
}
setContentView(R.layout.activity_main);
}
private void startTheServices()
{
Intent intent = new Intent(this, BackgroundServices.class);
startService(intent);
}
}
public class BackgroundServices extends Service {
#Override
public void onCreate(){
super.onCreate();
Toast.makeText(this, "This is on Create", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "This is on onStartCommand", Toast.LENGTH_LONG).show();
Thread thread = new Thread(new ThreadClass(startId));
thread.start();
return super.onStartCommand(intent, flags, startId);
//return START_STICKY;
}
#Override
public void onDestroy(){
super.onDestroy();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
final class ThreadClass implements Runnable {
int _serviceId;
ThreadClass(int serviceId) {
_serviceId = serviceId;
}
#Override
public void run() {
DirectoryObserver directoryObserver = new DirectoryObserver(new File(Environment.getExternalStorageDirectory(), Constants.Camera_Directory).getAbsolutePath(), getApplicationContext());
directoryObserver.startWatching();
}
}
}
public class DirectoryObserver extends FileObserver {
private static final String TAG = "DIRECTORY_OBERSVER";
private String directoryPath;
private Context _context;
public DirectoryObserver(String path, Context context) {
super(path);
Log.i(TAG, "Something Happening " + path);
_context = context;
directoryPath = path;
}
#Override
public void onEvent(int event, #Nullable String path) {
if (path == null) {
return;
}
//a new file or subdirectory was created under the monitored directory
if ((FileObserver.CREATE & event)!=0) {
Log.i(TAG, "A file is added to the path " + path);
Toast.makeText(_context, "A new file has been added", Toast.LENGTH_LONG).show();
}
if ((FileObserver.DELETE & event)!=0) {
Log.i(TAG, "A file is deleted to the path " + path);
//Context.getApplicationContext();
}
}
}
And following is the menifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="someone.package">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".BackgroundServices" android:exported="false"></service>
</application>
</manifest>
Have You Added The Permission? I Don't Have Enough Reps Otherwise I Would have Commented.
The problem here is that the FileObserver is probably being garbage collected, as you can see here:
Warning: If a FileObserver is garbage collected, it will stop sending events. To ensure you keep receiving events, you must keep a reference to the FileObserver instance from some other live object.
Android might be getting rid of your service, or even the FileObserver itself. Try to see if the code is entering the "startWatching()" method, or even if the service is starting.
The solution I found is that move the following initialization of DirectoryObserver
DirectoryObserver directoryObserver = new DirectoryObserver(new File(Environment.getExternalStorageDirectory(), Constants.Camera_Directory).getAbsolutePath(), getApplicationContext());
to
public int onStartCommand(Intent intent, int flags, int startId)
method in BackgroundService Class before following lines
Thread thread = new Thread(new ThreadClass(startId));
thread.start();

How to communicate with HostApduService from an Activity

I have asked this question here but it was marked as duplicate -
however I didn't find any solution helpful mentioned in comments.
Here, I am asking again with more details ...
I am doing a sample app (PoC) on HCE and using HostApduService as per Android user guide. I have created two apps
1) ReaderApp - acting as card reader
2) HCEApp - emulating a card
In HCEApp, I have created a class 'MyService' extending HostApduService
public class MyService extends HostApduService {
private int messageCounter;
private final String TAG = "MyService";
Intent mIntent;
#Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "onCreate");
mIntent = new Intent(this, MyActivity.class);
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(mIntent);
}
/**
* returned bytes will be sent as response. This method runs in Main thread
* so return ASAP.
*/
#Override
public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
if (selectAidApdu(apdu)) {
Log.i(TAG, "Application selected");
return getWelcomeMessage();
} else {
Log.i(TAG, "Received: " + new String(apdu));
return getNextMessage();
}
}
private byte[] getWelcomeMessage() {
return "Hello Desktop!".getBytes();
}
private byte[] getNextMessage() {
return ("Message from android: " + messageCounter++).getBytes();
}
private boolean selectAidApdu(byte[] apdu) {
if (apdu != null) {
for (byte b : apdu) {
System.out.printf("0x%02X", b);
}
}
return apdu.length >= 2 && apdu[0] == (byte) 0
&& apdu[1] == (byte) 0xa4;
}
#Override
public void onDeactivated(int reason) {
Log.i(TAG, "Deactivated: " + reason);
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
}
As you can see in onCreate(), I am launching MyActivity provides user to enter some information and needs to be sent back to MyService.
I think I can not use binding as 'onBind()' is declared final in HostApduService as below
#Override
public final IBinder onBind(Intent intent) {
return mMessenger.getBinder();
}
Please let me know if I am understading it correctly. Appreciate any help.
Thanks
iuq
Whether you can use onBind or not I do not know, but I recently worked with a BroadcastReceiver from which I had to start a Service. You cannot bind a Service from a BroadcastReceiver according to docs, you can only start it. I needed to send some data to the Service from my BroadcastReceiver at some later point, and since the binder techniques was not available to me, I had to find a different way to communicate with the Service, much like your case where you don't have a reference to it.
I did some research but could not find any solution, but then I remembered that you can pass intent data with the startService(intent) call. I start my Service work in onCreate instead, as onCreate is only called once when the Service is created.
In your Activity
public void sendDataToService(){
Intent intent = new Intent(context, MyService.class);
intent.putExtra("message", SOME_DATA);
context.startService(intent);
}
In your Service
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Check if intent has extras
if(intent.getExtras() != null){
// Get message
int message = intent.getExtras().getInt("message");
}
return START_NOT_STICKY;
}
This may be some sort what of a hack since "startService" does not sound like it should be used to send messages, and am not sure if this is exactly what you need, but it worked for me, so I hope it works for you. Cheers
Edit: BTW. I use it to tell a LocationService that a particular activity no longer want location updates.
I ended up taking a different approach to solving this same problem. When I bind to my HostApduService subclass, I grab a handle to the Messenger interface returned by the HostApduService onBind implementation.
Here's some sample code. This would all go in your activity implementation (calling it MyActivity here, communicating with MyHostApduServiceSubclass). Here's what MyActivity would need to include:
private Messenger mAPDUMessenger;
...
#Override
protected void onStart() {
super.onStart();
Context context = getApplicationContext();
Intent apduIntent = new Intent(montext, ContactlessApduService.class);
context.bindService(apduIntent, mAPDUConnection, Context.BIND_AUTO_CREATE);
}
...
private ServiceConnection mAPDUConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName className, IBinder service) {
// The HostApduService has a final override on the onBind() service method that returns
// an IMessageHandler interface that we can grab and use to send messages back to the
// terminal - would be better to get a handle to the running instance of the service so
// that we could make use of the HostApduService#sendResponseApdu public method
mAPDUMessenger = new Messenger(service);
registerAPDUMessengerIntentFilters();
// ^ This method sets up my handlers for local broadcast messages my BroadcastReceiver processes.
}
...
}
...
private void registerAPDUMessengerIntentFilters() {
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(MyActivity.this);
IntentFilter intentFilter = new IntentFilter(MyHostApduServiceSubclass.ACTION_PPSE_APDU_SELECT);
lbm.registerReceiver(apduMessageBroadcastReceiver, intentFilter);
}
...
BroadcastReceiver apduMessageBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(MyHostApduServiceSubclass.ACTION_PPSE_APDU_SELECT)) {
sendResponseApdu(MyActivity.PPSE_APDU_SELECT_RESPONSE_BYTES);
}
}
};
...
public final void sendResponseApdu(byte[] responseApdu) {
Message responseMsg = Message.obtain(null, MyHostApduServiceSubclass.MSG_RESPONSE_APDU);
// ^ Note here that because MSG_RESPONSE_APDU is the message type
// defined in the abstract HostApduService class, I had to override
// the definition in my subclass to expose it for use from MyActivity.
// Same with the KEY_DATA constant value below.
Bundle dataBundle = new Bundle();
dataBundle.putByteArray(MyHostApduServiceSubclass.KEY_DATA, responseApdu);
responseMsg.setData(dataBundle);
try {
mAPDUMessenger.send(responseMsg);
} catch (RemoteException e) {
// Do something with the failed message
}
}
And then your HostApduService subclass would just need to send a broadcast to your activity indicating what APDU command was received. Here is what would need to be included in MyHostApduServiceSubclass:
public static final String ACTION_PPSE_APDU_SELECT = "ACTION_PPSE_APDU_SELECT";
// Abstract super class constant overrides
public static final String KEY_DATA = "data";
public static final int MSG_RESPONSE_APDU = 1;
#Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
Context context = getApplicationContext();
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
if (Arrays.equals(MyHostApduServiceSubclass.PPSE_APDU_SELECT_BYTES, commandApdu)) {
lbm.sendBroadcast(new Intent(ACTION_PPSE_APDU_SELECT));
}
return null;
// ^ Note the need to return null so that the other end waits for the
// activity to send the response via the Messenger handle
}

Android RemoteService Unable to start Service Intent

I am trying to build a remote service to which I can bind to activities that will be used and created often. I think this is the best method for handling what it is I am trying to accomplish. I keep getting this error though.
Unable to start service Intent { act=com.services.OverheadService } U=0: not found
I would think something might be wrong with my manifest? But I don't see what, my manifest will be at the bottom of the related code here below.
Here is the Call within my onCreate() in my activity:
// TESTING SERVICE IMPLMENTATION TODO
Intent serviceIntent = new Intent("com.services.OverheadService");
boolean ok = this.bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
Log.v("ok", String.valueOf(ok));
Here is the Connection method:
/** SERVICE IMPLEMENTATION TESTING **/
private ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
// get instance of the aidl binder
mRemoteService = IRemoteService.Stub.asInterface(service);
try {
String message = mRemoteService.sayHello("Mina");
Log.v("message", message);
} catch (RemoteException e) {
Log.e("RemoteException", e.toString());
}
}
};
And here is the Service Class:
package com.services;
import com.services.IRemoteService.Stub;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class OverheadService extends Service {
#Override
public IBinder onBind(Intent arg0) {
return mBinder;
}
// implementation of the aidl interface
private final IRemoteService.Stub mBinder = new Stub() {
#Override
public String sayHello(String message) throws RemoteException {
return "Hello " + message;
}
};
}
AndroidManifest where the service is being set:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<service
android:name="com.services.OverheadService"
android:enabled="true"
android:icon="#drawable/failed_load" >
<!--
intent-filter>
<action android:name="com.cdkdevelopment.BaseActivity" />
</intent-filter>
-->
</service>
I have found the solution and it was changing this in the onCreate
Intent serviceIntent = new Intent(this, OverheadService.class);
boolean ok = this.getApplicationContext().bindService(serviceIntent,
mServiceConnection, Context.BIND_AUTO_CREATE);
Log.v("ok", String.valueOf(ok));

Categories

Resources