Я разрабатываю программное обеспечение для отслеживания GPS на Android. Мне нужен IPC для управления сервисом от разных видов деятельности. Поэтому я решил разработать удаленный сервис с AIDL. Это не было большой проблемой, но теперь он всегда работает с методами интерфейса, а не с методами моего класса обслуживания. Может быть, кто-то может мне помочь?
Вот мой файл AIDL:
package test.de.android.tracker
interface ITrackingServiceRemote {
void startTracking(in long trackId);
void stopTracking();
void pauseTracking();
void resumeTracking(in long trackId);
long trackingState();
}
А вот краткая версия моего класса обслуживания:
public class TrackingService extends Service implements LocationListener{
private LocationManager mLocationManager;
private TrackDb db;
private long trackId;
private boolean isTracking = false;
@Override
public void onCreate() {
super.onCreate();
mNotificationManager = (NotificationManager) this
.getSystemService(NOTIFICATION_SERVICE);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
db = new TrackDb(this.getApplicationContext());
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
@Override
public void onDestroy(){
//TODO
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent){
return this.mBinder;
}
private IBinder mBinder = new ITrackingServiceRemote.Stub() {
public void startTracking(long trackId) throws RemoteException {
TrackingService.this.startTracking(trackId);
}
public void pauseTracking() throws RemoteException {
TrackingService.this.pauseTracking();
}
public void resumeTracking(long trackId) throws RemoteException {
TrackingService.this.resumeTracking(trackId);
}
public void stopTracking() throws RemoteException {
TrackingService.this.stopTracking();
}
public long trackingState() throws RemoteException {
long state = TrackingService.this.trackingState();
return state;
}
};
public synchronized void startTracking(long trackId) {
// request updates every 250 meters or 0 sec
this.trackId = trackId;
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 250, this);
isTracking = true;
}
public synchronized long trackingState() {
if(isTracking){
return trackId;
} else
return -1;
}
public synchronized void stopTracking() {
if(isTracking){
mLocationManager.removeUpdates(this);
isTracking = false;
} else
Log.i(TAG, "Could not stop because service is not tracking at the moment");
}
public synchronized void resumeTracking(long trackId) {
if(!isTracking){
this.trackId = trackId;
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 250, this);
isTracking = true;
} else
Log.i(TAG, "Could not resume because service is tracking already track " + this.trackId);
}
public synchronized void pauseTracking() {
if(isTracking){
mLocationManager.removeUpdates(this);
isTracking = false;
} else
Log.i(TAG, "Could not pause because service is not tracking at the moment");
}
public void onLocationChanged(Location location) {
//TODO
}
Для более легкого доступа с клиента я написал класс ServiceManager, который устанавливает ServiceConnection, и вы можете вызывать методы сервиса. Вот мой код для этого:
public class TrackingServiceManager{
private static final String TAG = "TrackingServiceManager";
private ITrackingServiceRemote mService = null;
private Context mContext;
private Boolean isBound = false;
private ServiceConnection mServiceConnection;
public TrackingServiceManager(Context ctx){
this.mContext = ctx;
}
public void start(long trackId) {
if (isBound && mService != null) {
try {
mService.startTracking(trackId);
} catch (RemoteException e) {
Log.e(TAG, "Could not start tracking!",e);
}
} else
Log.i(TAG, "No Service bound! 1");
}
public void stop(){
if (isBound && mService != null) {
try {
mService.stopTracking();
} catch (RemoteException e) {
Log.e(TAG, "Could not stop tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public void pause(){
if (isBound && mService != null) {
try {
mService.pauseTracking();
} catch (RemoteException e) {
Log.e(TAG, "Could not pause tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public void resume(long trackId){
if (isBound && mService != null) {
try {
mService.resumeTracking(trackId);
} catch (RemoteException e) {
Log.e(TAG, "Could not resume tracking!",e);
}
} else
Log.i(TAG, "No Service bound!");
}
public float state(){
if (isBound && mService != null) {
try {
return mService.trackingState();
} catch (RemoteException e) {
Log.e(TAG, "Could not resume tracking!",e);
return -1;
}
} else
Log.i(TAG, "No Service bound!");
return -1;
}
/**
* Method for binding the Service with client
*/
public boolean connectService(){
mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
TrackingServiceManager.this.mService = ITrackingServiceRemote.Stub.asInterface(service);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
if (mService != null) {
mService = null;
}
}
};
Intent mIntent = new Intent("test.de.android.tracker.action.intent.TrackingService");
this.isBound = this.mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
return this.isBound;
}
public void disconnectService(){
this.mContext.unbindService(mServiceConnection);
this.isBound = false;
}
}
Если я сейчас попытаюсь вызвать метод из действия, например start (trackId), ничего не произойдет. Привязка в порядке. При отладке он всегда запускается в startTracking () в сгенерированном файле ITrackingServiceRemote.java, а не в моем классе TrackingService. В чем проблема? Я не могу найти ничего плохого.
Заранее спасибо!
Tobias