Reputation: 274
I would like to provide a service that can be called by other app. Therefore, I have a service and an aidl. But when I try to have a separate application to bind this service (bindService), it just returns me false which means fail. Here is my code.
I'm using the code from books Pro Android 2
I've already tried many solutions in other questions similar to this, but there isn't any working solution for me.
I've tried fix the aidl intent filter but it's still not working
I've tried fix the package name and class name in client app, but it's still not working.
Please help me!
On Client :
// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
// Declare any non-default types here with import statements
interface IStockQuoteService {
double getQuote(String ticker);
}
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteclient;
import id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
protected static final String TAG = "StockQuoteClient";
private IStockQuoteService stockService = null;
private Button bindBtn;
private Button callBtn;
private Button unbindBtn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bindBtn = (Button)findViewById(R.id.bindBtn);
bindBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.IStockQuoteService");
Log.d("Hasil", String.valueOf(bindService(intent,
serConn, Context.BIND_AUTO_CREATE)));
bindBtn.setEnabled(false);
callBtn.setEnabled(true);
unbindBtn.setEnabled(true);
}});
callBtn = (Button)findViewById(R.id.callBtn);
callBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
callService();
}});
callBtn.setEnabled(false);
unbindBtn = (Button)findViewById(R.id.unbindBtn);
unbindBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View view) {
unbindService(serConn);
bindBtn.setEnabled(true);
callBtn.setEnabled(false);
unbindBtn.setEnabled(false);
}});
unbindBtn.setEnabled(false);
}
private void callService() {
try {
double val = stockService.getQuote("SYH");
Toast.makeText(MainActivity.this, "Value from service is "+val,
Toast.LENGTH_SHORT).show();
} catch (RemoteException ee) {
Log.e("MainActivity", ee.getMessage(), ee);
}
}
private ServiceConnection serConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
Log.v(TAG, "onServiceConnected() called");
stockService = IStockQuoteService.Stub.asInterface(service);
callService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.v(TAG, "onServiceDisconnected() called");
stockService = null;
}
};
}
On Service :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice">
<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="StockQuoteService">
<intent-filter>
<action android:name="com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice.IStockQuoteService"
/>
</intent-filter>
</service>
</application>
</manifest>
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class StockQuoteService extends Service
{
private static final String TAG = "StockQuoteService";
public class StockQuoteServiceImpl extends IStockQuoteService.Stub
{
@Override
public double getQuote(String ticker) throws RemoteException
{
Log.v(TAG, "getQuote() called for " + ticker);
return 20.0;
}
}
@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, "onCreate() called");
}
@Override
public void onDestroy()
{
super.onDestroy();
Log.v(TAG, "onDestroy() called");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.v(TAG, "onStart() called");
}
@Override
public IBinder onBind(Intent intent)
{
Log.v(TAG, "onBind() called");
return new StockQuoteServiceImpl();
}
}
// IStockQuoteService.aidl
package id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice;
// Declare any non-default types here with import statements
interface IStockQuoteService {
double getQuote(String ticker);
}
Upvotes: 1
Views: 962
Reputation: 1007369
I'm using the code from books Pro Android 2
That book is from 2010. Much of that book will be out of date. Please use something newer. If nothing else, you can download older editions of one of my books for free. Right now, the most recent version of those is from 2015 — while that too is a bit old, it is much more up to date than a book from 2010.
I've already tried many solutions in other questions similar to this, but there isn't any working solution for me.
You have:
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.IStockQuoteService");
The package
in your manifest has id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain.stockquoteservice
. Assuming that your applicationId
in your module's build.gradle
file is the same, I think that this matches what you have in your code. Your application ID is very long — in the future, I recommend that you use something shorter and easier to visually compare.
However, your class name is wrong. Your <service>
class is StockQuoteService
, not IStockQuoteService
. IStockQuoteService
is the name of the AIDL, not the service, and your Intent
needs to point to the service. So, try:
intent.setClassName("com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice",
"com.id.ac.ui.cs.mobileprogramming.ahmad_fauzan_amirul_isnain" +
".stockquoteservice.StockQuoteService");
Or, to reduce duplication:
String packageName = "com.id.ac.ui.cs.mobileprogramming" +
".ahmad_fauzan_amirul_isnain.stockquoteservice";
intent.setClassName(packageName, packageName+".StockQuoteService");
Upvotes: 1