Beacons not detected in Android service - android

I'm using the Altbeacon library (stable release 2.1.4) to detect beacons. If I do it in an Activity, I have no problems detecting them. However I can't get this to work from a service. Here's what I've got:
package com.ibeacontest.android;
import java.util.Collection;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class TestBestzBeaconService extends Service implements BeaconConsumer
{
private BeaconManager beaconManager;
private final String BEACON_UUID = "11687109-915f-4136-a1f8-e60ff514f96d";
private final int BEACON_MAJOR = 3;
#Override
public void onCreate() {
super.onCreate();
L.p("In TestBestzBeaconService onCreate()");
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand (Intent intent, int flags, int startId) {
L.p("in TestBestzBeaconService onStartCommand()");
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.bind(this);
//iBeacons ?
BeaconParser bp0 = new BeaconParser();
bp0.setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24");
beaconManager.getBeaconParsers().add(bp0);
//Bluecats?
BeaconParser bp1 = new BeaconParser();
bp1.setBeaconLayout("m:2-3=0201,i:28-29,p:24-24");
beaconManager.getBeaconParsers().add(bp1);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
L.p("In TestBestzBeaconService onDestroy()");
beaconManager.unbind(this);
}
#Override
public void onBeaconServiceConnect() {
L.p("In TestBestzBeaconService onBeaconServiceConnect()");
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> arg0, Region arg1) {
L.p("In TestBestzBeaconService - anonymous didRangeBeaconsInRegion()");
}
});
Region region = new Region("myregion", Identifier.parse(BEACON_UUID), Identifier.fromInt(BEACON_MAJOR), null); //
try {
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
L.p("In TestBestzBeaconService onBeaconServiceConnect(), REMOTEEXCEPTION!");
}
}
private static class L
{
public static void p(String s) {
Log.i("beacon", s);
}
}
}
I'm calling this from an Activity as so:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this, TestBestzBeaconService.class));
}
}
The log output I'm getting is:
03-19 09:56:40.233: I/beacon(25210): In TestBestzBeaconService onCreate()
03-19 09:56:40.233: I/beacon(25210): in TestBestzBeaconService onStartCommand()
03-19 09:56:40.566: I/beacon(25210): In TestBestzBeaconService onBeaconServiceConnect()
Parts added to the AndroidManifest:
<!-- Needed for AltBeacon SDK -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
and inside the Application tag:
<!-- Needed for AltBeacon SDK -->
<service android:name="org.altbeacon.beacon.service.BeaconService"/>
<service android:name="com.ibeacontest.android.TestBestzBeaconService" />
...but no signs of beacons or the didRangeBeaconsInRegion log output. Any pointers?

As i know Monitoring only works in background while Ranging do not. Try firstly starting a Monitoring and then immediately when you enter Monitoring start Ranging.
Something like:
//Set Monitoring
mBeaconManager.setMonitorNotifier(new
MonitorNotifier() {
#Override
public void didEnterRegion (Region region){
Log.d("TEST", "ENTERED beacon region");
//Start Raning as soon as you detect a beacon
try {
mBeaconManager.startRangingBeaconsInRegion(mRegion);
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
//Set Ranging
mBeaconManager.setRangeNotifier(new
RangeNotifier() {
#Override
public void didRangeBeaconsInRegion ( final Collection<Beacon> beacons, Region region){
if (beacons.size() > 0) {
Log.i(TAG, p("In TestBestzBeaconService - anonymous
}
}
});
try
{
//Start Monitoring
mBeaconManager.startMonitoringBeaconsInRegion(mRegion);
}
catch(RemoteException e)
{
e.printStackTrace();
}
Don't forget to add beacon service to Manifest:
<service
android:name="org.altbeacon.beacon.service.BeaconService"
android:enabled="true"
android:exported="true"
android:isolatedProcess="false"
android:label="beacon"></service>
<service
android:name="org.altbeacon.beacon.BeaconIntentProcessor"
android:enabled="true"></service>
note: In meantime check also lib project

The posted code is in a library project and contained the correct inserts in the AndroidManifest file, however the actual app project was missing this.
I believe normally this would cause the app to crash, but in this case it just wouldn't show beacons.
Adding this made it work.

Related

How to calculate the distance of ibeacon using android studio

I tried to calculate my ibeacon distance using android studio , i followed a video tutorial in http://www.software7.com/blog/creating-a-beacon-app-for-android-in-less-than-10-minutes-from-scratch/ , i did exactly the same as he did , however he didn't use android studio instead IntelliJ IDEA . The result should be appear at android monitor - logcat , but mine didn't
import android.os.RemoteException;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.Identifier;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import java.util.Collection;
public class MainActivity extends AppCompatActivity implements
BeaconConsumer {
public static final String TAG = "BeaconsEverywhere";
private BeaconManager beaconManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
beaconManager = BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-
24,d:25-25"));
beaconManager.bind(this);
}
#Override
public void onBeaconServiceConnect() {
final Region region = new Region("myBeaons", Identifier.parse("2173E519-
9155-4862-AB64-7953AB146156"),null,null);
beaconManager.addMonitorNotifier(new MonitorNotifier() {
#Override
public void didEnterRegion(Region region) {
try {
Log.d(TAG,"didEnterRegion");
beaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didExitRegion(Region region) {
try {
Log.d(TAG,"didExitRegion");
beaconManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
}
#Override
public void didDetermineStateForRegion(int i, Region region) {
}
});
beaconManager.addRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons,
Region region) {
for(Beacon oneBeacon : beacons){
Log.d(TAG, "distance: " + oneBeacon.getDistance() + " id:" +
oneBeacon.getId1() + "/" + oneBeacon.getId2() + "/" +
oneBeacon.getId3());
}
}
});
try {
beaconManager.startMonitoringBeaconsInRegion(region);
}catch (RemoteException e){
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
}
The first Image is my expectation , second is my result
would you guys help me to figure out what the problem is ?
I would add new debug lines like Log.d(TAG,"onCreate"); and Log.d(TAG,"onBeaconServiceConnect"); in each of those methods so you can tell what is going on, then look for those lines when you run your app. This will tell you how far your program is getting in the process.
I also suspect that you will need to use a different beacon parser expression than is listed here:
beaconManager.getBeaconParsers().add(new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-
24,d:25-25"));
If you are using an off-the-shelf iBeacon, you will need to replace that string with the iBeacon layout as can be found here:
https://beaconlayout.wordpress.com/
Don't worry about Android Studio vs. IntelliJ IDEA. The code shown should work fine using either IDE.

Radius Network Beacon Library 2.0 (AltBeacon) unable to detect Beacons

Hello I'm currently using Radius Network Beacon SDK but unable to detect my beacons.
In didRangeBeaconsInRegion(Collection beacons, Region region) collection object size is 0
Please help me!!
RangingActivity Code-
import java.util.Collection;
import android.app.Activity;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.widget.EditText;
import org.altbeacon.beacon.AltBeacon;
import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
public class RangingActivity extends Activity implements BeaconConsumer {
protected static final String TAG = "RangingActivity";
private BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ranging);
beaconManager.bind(this);
beaconManager.debug = true;
}
#Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
#Override
protected void onPause() {
super.onPause();
}
#Override
protected void onResume() {
super.onResume();
}
#Override
public void onBeaconServiceConnect() {
beaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if (beacons.size() > 0) {
EditText editText = (EditText)RangingActivity.this
.findViewById(R.id.rangingText);
Beacon firstBeacon = beacons.iterator().next();
logToDisplay("The first beacon "+firstBeacon.toString()+" is about "+firstBeacon.getDistance()+" meters away.");
}
}
});
try {
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));
//beaconManager.updateScanPeriods();
} catch (RemoteException e) { }
}
private void logToDisplay(final String line) {
runOnUiThread(new Runnable() {
public void run() {
EditText editText = (EditText)RangingActivity.this
.findViewById(R.id.rangingText);
editText.append(line+"\n");
}
});
}
}
You need a custom Parser to properly recognize that beacons.
Take a look at this answer:
Is this the correct layout to detect iBeacons with AltBeacon's Android Beacon Library?
You need to call the onBeaconConnect() in your onCreate function
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ranging);
beaconManager.bind(this);
beaconManager.debug = true;
onBeaconConnect()
}

startService() not running in android

I'm trying to run startService() in my android app, but it is not working.
Here is the code from the call to start the service:
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
stopService(mPositioningIntent);
startService(mPositioningIntent);
Here is the code from MyGeoloqiPositioning.java (note, this is taken with minor modifications from the source code of MapAttack)
package com.example.manhunttwopointoh;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.util.Pair;
import android.widget.Toast;
import com.example.manhunttwopointoh.MyFix;
import com.example.manhunttwopointoh.MyGeoloqiFixSocket;
import com.example.manhunttwopointoh.MyUDPClient;
public class MyGeoloqiPositioning extends Service implements LocationListener {
public static final String TAG = "GeoloqiPositioning";
private int batteryLevel = 0;
MyGeoloqiFixSocket fixSocket;
#Override
public void onCreate() {
android.os.Debug.waitForDebugger();
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onCreate()", Toast.LENGTH_LONG).show();
if (isConnected()) {
fixSocket = MyUDPClient.getApplicationClient(this);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable! Stopping positioning service.");
stopSelf();
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStart()", Toast.LENGTH_LONG).show();
registerReceiver(batteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
for (String provider : ((LocationManager) getSystemService(LOCATION_SERVICE)).getAllProviders()) {
if (!provider.equals("passive")) {
MyADB.log("Registering for updates with " + provider);
((LocationManager) getSystemService(LOCATION_SERVICE)).requestLocationUpdates(provider, 0, 0, this);
}
}
}
public void onStop() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public void onDestroy() {
unregisterReceiver(batteryReceiver);
((LocationManager) getSystemService(LOCATION_SERVICE)).removeUpdates(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onStartCommand()", Toast.LENGTH_LONG).show();
onStart(intent, startid);
return Service.START_REDELIVER_INTENT;
}
#Override
public void onLocationChanged(Location location) {
Toast.makeText(MyGeoloqiPositioning.this, "MyGeoloqiPositiong in onLocationChanged()", Toast.LENGTH_LONG).show();
#SuppressWarnings("unchecked")
MyFix lqLocation = new MyFix(location, new Pair<String, String>("battery", "" + batteryLevel));
if (isConnected()) {
fixSocket.pushFix(lqLocation);
} else {
// TODO: This is a crude check. Should probably be rolled into UDPClient class directly.
Log.w(TAG, "Network unavailable, failed to push location fix!");
}
}
#Override
public void onProviderDisabled(String provider) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
batteryLevel = intent.getIntExtra("level", 0);
}
};
/** Determine if the network is connected and available. */
private boolean isConnected() {
ConnectivityManager manager = (ConnectivityManager) getApplicationContext()
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
return (activeNetwork != null && activeNetwork.isConnected());
}
}
I tried inserting a breakpoint in MyGeoloqiPositioning, but nothing ever comes of it. I also put various Toast() calls, but still no dice. My GeoloqiPositioning.java is never called. What am I doing wrong?
EDIT:
Here is the new code from the manifest file:
<service
android:name="com.manhunttwopointoh.MyGeoloqiPositioning"
android:enabled="true"
android:exported="false"
android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
I tried adding the intent-filter tags, but still nothing. I also have nothing registering on the logs. Here is the code (commented out stopService()):
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_geoloqi);
Intent mPositioningIntent = new Intent(this, MyGeoloqiPositioning.class);
//stopService(mPositioningIntent);
startService(mPositioningIntent);
Toast.makeText(PreyGeoloqi.this, "testing mPositioningIntent: " + mPositioningIntent.toString(), Toast.LENGTH_LONG).show();
}
I still get nothing. Do I need to explicitly call methods in MyPreyGeoloqi.java? I am fairly confused...
Try adding an intent filter your service definition in the AndroidManifest:
<!-- snippet from Android Manifest file -->
<service android:name="com.manhunttwopointoh.MyGeoloqiPositioning" android:enabled="true" android:process=":lqRemote" >
<intent-filter>
<action android:name="com.manhunttwopointoh.MyGeoloqiPositioning" />
</intent-filter>
</service>
This allows your service to receive the intent sent from your Activity.

Android remote service executing but onStartCommand never called

So after 2-3 hours of failures i finally got my remote service to work somehow but it's acting real strange.
I'm using AIDL to send mediaPath string to my service and it starts playing music just fine, but the onStartCommand never gets called and the Service entry in Apps doesn't have the label/description I set in the manifest file. [http://i50.tinypic.com/344p349.png]
Also the Service terminates if I terminate the main Activity process, although it resides in a separate process. Is this how it's supposed to be? [http://i49.tinypic.com/16hpa86.png]
And I never get the "Service disconnected" Log which should happen when Service gets unbound from Activity.
Service code:
package com.example.randomserviceshitnot;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MojPrviServis extends Service {
private final Servis.Stub binder = new Servis.Stub() {
public void execute(String mediaPath) throws RemoteException {
MediaPlayer mp = new MediaPlayer();
try {
mp.setDataSource(mediaPath);
mp.prepare();
} catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) {
e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace();
} catch (IOException e) { e.printStackTrace(); }
mp.start();
}
};
public void onCreate() {
super.onCreate();
Log.d("Filip", "Service onCreate called.");
}
public IBinder onBind(Intent intent) {
return binder;
}
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("Filip ", "Service onStart called.");
return START_STICKY;
}
}
Activity code:
package com.example.randomserviceshitnot;
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.Environment;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
public class MainActivity extends Activity {
private Servis mBoundService;
private boolean mIsBound = false;
private static final String mediaPath = Environment.getExternalStorageDirectory().toString()+"/Music/Art Of The Dress(Archie Remix).mp3";
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("Filip ", "Service connected.");
mBoundService = Servis.Stub.asInterface(service);
try {
mBoundService.execute(mediaPath);
} catch (RemoteException e) {
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
Log.d("Filip ", "Service disconnected.");
mBoundService = null;
}
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
doBindService();
}
void doBindService() {
Intent s = new Intent();
s.setAction("remote.servis");
bindService(s, mConnection, Context.BIND_AUTO_CREATE);
mIsBound = true;
}
#Override
protected void onDestroy() {
super.onDestroy();
doUnbindService();
}
public void onPause() {
super.onPause();
doUnbindService();
}
void doUnbindService() {
if(mIsBound) {
unbindService(mConnection);
mIsBound=false;
}
}
}
AIDL:
package com.example.randomserviceshitnot;
interface Servis {
void execute(String s);
}
Manifest:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.randomserviceshitnot"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/title_activity_main" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MojPrviServis"
android:label="#string/servis_koji_notifikuje"
android:description="#string/proces_desc"
android:icon="#drawable/ic_launcher"
android:process=":dep" >
<intent-filter>
<action android:name="remote.servis" />
</intent-filter>
</service>
</application>
</manifest>
http://developer.android.com/guide/components/services.html
Read the documentation of onStartCommand() and onBind()
When you call bindService() onStartCommand() is NOT called. But onBind() is called.
Also the service terminates if all the clients exited if the service was stared with bindservice().
For playing music you should use startService() instead of bind. If service is started this way then it does not stop when client exists. It has to stop itself when done.

Why can't we call api of android (AIDL based) remote service directly?

I was writing a simple AIDL based android remote service & a client to access the API exposed by the remote service. I checked on the internet, in every posts people have called the remote service API inside button's onClickListener() method of client code. However when i tried to call the API exposed by remote service outside the onClickListener() method it throws me NullPointerException, indicating that my service object has not been initialized (Please check the comments inside the onCreate method of client code). I have attached my code with this question. If anyone can explain me why is the behavior so then that would be really great.
Here is client code :
package com.myapp.myclient;
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.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
import com.myapp.myservice.RemoteServiceInterface;
public class MyClient extends Activity {
RemoteServiceInterface remoteInterface;
ServiceConnection connection;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent i = new Intent();
i.setAction("com.myapp.myservice.RemoteService");
startRemoteInterface(i);
bindRemoteInterface(i);
/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
/* Whereas this code does work. */
Button getMessage = (Button)findViewById(R.id.getMessage);
getMessage.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String msg = null;
try {
msg = remoteInterface.getMessage();
} catch (RemoteException e) {
e.printStackTrace();
}
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT).show();
}
});
}
class RemoteServiceConnection implements ServiceConnection{
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
remoteInterface = RemoteServiceInterface.Stub.asInterface(service);
}
#Override
public void onServiceDisconnected(ComponentName name) {
}
}
private void startRemoteInterface(Intent i) {
startService(i);
}
private void bindRemoteInterface(Intent i) {
if(connection == null){
connection = new RemoteServiceConnection();
bindService(i, connection, Context.BIND_AUTO_CREATE);
} else {
Toast.makeText(getBaseContext(), "Service cannot bind - already bound.", Toast.LENGTH_SHORT).show();
}
}
}
Here is my remote service code:
package com.myapp.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
public class RemoteService extends Service {
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
#Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
private final RemoteServiceInterface.Stub mBinder = new RemoteServiceInterface.Stub() {
#Override
public String getMessage() throws RemoteException {
return "Hello World!";
}
};
}
Here is my aidl file :
package com.myapp.myservice;
interface RemoteServiceInterface {
String getMessage();
}
Thanks in advance,
Rupesh
bindRemoteInterface(i);
/* This code doesn't execute. Raises a Null Pointer
Exception, indicating that remoteInterface is not
initialized. */
try {
Toast.makeText(getBaseContext(), remoteInterface.getMessage(), Toast.LENGTH_SHORT).show();
} catch (RemoteException e) {
e.printStackTrace();
}
Please keep in mind that the bind is an asychronus call you have to wait for the callback in the ServiceConnection for onServiceConnected and perform actions after that.
Also you have to use the asInterface method to get the real interface for your connection this is demonstrated by the google aidl example
RemoteServiceInterface mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Following the example above for an AIDL interface,
// this gets an instance of the IRemoteInterface, which we can use to call on the service
mIRemoteService = RemoteServiceInterface.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
mIRemoteService = null;
}
};
You can then make the call on the mIRemoteService object. either directly in the onServiceConnected callback or by notifying the service.
remoteInterface is NULL before service is connected (onServiceConnected called) .
startService is an async call, you call startService don't mean the service is started and connected . when service is connected , onServiceConnected is called , then you can use the connection to call remote service .
Actually , you should always check weather remoteInterface is null or not .

Categories

Resources