android:versionName="1.0">
<!-- Permissions -->
- <uses-permission
- android:name="android.permission.INTERNET" />
- <uses-permission
- android:name="android.permission.ACCESS_COARSE_LOCATION"/>
- <uses-permission
- android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission
- android:name="android.permission.ACCESS_NETWORK_STATE"/>
- <uses-permission
- android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission
- android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
- <uses-permission
- android:name="com.example.permission.MAPS_RECEIVE"/>
- <permission
- android:name="com.example.permission.MAPS_RECEIVE"
- android:protectionLevel="signature"/>
+ <uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<!-- Features -->
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<uses-sdk
- android:minSdkVersion="16"
+ android:minSdkVersion="18"
android:targetSdkVersion="18" />
<!-- Application -->
</activity>
<activity android:name="Prefs" />
<service android:name="Task" />
+ <service android:name="com.radiusnetworks.ibeacon.service.IBeaconService"
+ android:enabled="true"
+ android:exported="true"
+ android:isolatedProcess="false"
+ android:label="iBeacon" />
+ <service android:name="com.radiusnetworks.ibeacon.IBeaconIntentProcessor"
+ android:enabled="true" />
<uses-library android:name="com.google.android.maps" />
<meta-data
android:name="com.google.android.gms.version"
ANDROID ?= /opt/android-sdk-update-manager/platforms/android-18/android.jar
SDKLIB ?= /opt/android-sdk-update-manager/tools/lib/sdklib.jar
MAPLIB ?= /opt/android-sdk-update-manager/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar
+IBEACON ?= /home/andy/class/AndroidIBeaconLibrary/libs/classes.jar
TOOLS ?= /opt/android-sdk-update-manager/build-tools/19.0.1
# Variables
# ADB targets
logcat:
- adb logcat $(PROGRAM):D AndroidRuntime:E '*:S'
+ adb logcat $(PROGRAM):D IBeaconManager:D AndroidRuntime:E '*:S'
run: bin/install.stamp
adb shell am start -W \
@zipalign -f 4 $@.in $@
%.dex: $(OBJ) makefile | bin
- @echo "DEX $@ obj $(notdir $(MAPLIB))"
- @dx --dex --output $@ obj $(MAPLIB)
+ @echo "DEX $@ obj $(notdir $(MAPLIB)) $(notdir $(IBEACON))"
+ @dx --dex --output $@ obj $(MAPLIB) $(IBEACON)
%.res: AndroidManifest.xml $(RES) | bin
@echo "RES $@"
-M AndroidManifest.xml \
-S res \
-S /opt/android-sdk-update-manager/extras/google/google_play_services/libproject/google-play-services_lib/res \
+ -S /home/andy/class/AndroidIBeaconLibrary/res \
-F $*.res
$(OBJ): $(SRC) $(GEN) makefile | obj
@echo "JAVAC obj/*.class $+"
- @JARS=$(ANDROID):$(MAPLIB); \
+ @JARS=$(ANDROID):$(MAPLIB):$(IBEACON); \
javac -g \
-Xlint:unchecked \
-Xlint:deprecation \
$(GEN): AndroidManifest.xml $(RES) | gen
@echo "GEN $@"
+ @aapt package -f -m \
+ -I $(ANDROID) \
+ -M /home/andy/class/AndroidIBeaconLibrary/AndroidManifest.xml \
+ -S /home/andy/class/AndroidIBeaconLibrary/res \
+ -J gen
@aapt package -f -m \
-I $(ANDROID) \
-M /opt/android-sdk-update-manager/extras/google/google_play_services/libproject/google-play-services_lib/AndroidManifest.xml \
-M AndroidManifest.xml \
-S res \
-S /opt/android-sdk-update-manager/extras/google/google_play_services/libproject/google-play-services_lib/res \
+ -S /home/andy/class/AndroidIBeaconLibrary/res \
-J gen
# Directories
private Messenger messenger;
private Task task;
private Toast toast;
- private boolean running;
/* Widgets */
private TabHost window;
{
Util.debug("Main: onRegister");
this.task = task;
- this.running = this.task.isRunning();
}
private void onPosition()
{
Util.debug("Main: register");
startService(new Intent(this, Task.class)
- .putExtra("Command", Task.REGISTER)
+ .putExtra("Command", Task.Command.REGISTER)
.putExtra("Messenger", this.messenger));
}
{
Util.debug("Main: connect");
startService(new Intent(this, Task.class)
- .putExtra("Command", Task.CONNECT));
- this.running = true;
+ .putExtra("Command", Task.Command.CONNECT));
}
private void disconnect()
{
Util.debug("Main: disconnect");
startService(new Intent(this, Task.class)
- .putExtra("Command", Task.DISCONNECT));
- this.running = false;
+ .putExtra("Command", Task.Command.DISCONNECT));
}
private void quit()
@Override
public boolean onPrepareOptionsMenu(Menu menu)
{
- menu.findItem(R.id.connect).setVisible(!this.running);
- menu.findItem(R.id.disconnect).setVisible(this.running);
+ boolean running = this.task != null && this.task.isRunning();
+ menu.findItem(R.id.connect).setVisible(!running);
+ menu.findItem(R.id.disconnect).setVisible(running);
return true;
}
{
public void handleMessage(android.os.Message msg)
{
- switch (msg.what) {
- case Task.REGISTER:
- Main.this.onRegister((Task)msg.obj);
- break;
- case Task.POSITION:
+ Task.Response resp = Task.Response.values()[msg.what];
+ switch (resp) {
+ case POSITION:
Main.this.onPosition();
break;
- case Task.CONNECT:
- Main.this.running = true;
- break;
- case Task.DISCONNECT:
- Main.this.running = false;
- break;
- case Task.NOTIFY:
+ case NOTIFY:
Main.this.onNotify((String)msg.obj);
break;
default:
- Util.debug("Main: unknown message - " + msg.what);
+ Util.debug("Main: unknown message - " + resp);
break;
}
}
import java.util.List;
import java.util.LinkedList;
+import java.util.Collection;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import android.os.IBinder;
import android.os.Looper;
import android.os.Messenger;
+import android.os.RemoteException;
import android.preference.PreferenceManager;
-public class Task extends Service implements Runnable
+import com.radiusnetworks.ibeacon.*;
+import com.radiusnetworks.ibeacon.client.*;
+import com.radiusnetworks.ibeacon.service.*;
+
+public class Task extends Service implements IBeaconConsumer, RangeNotifier, MonitorNotifier
{
- /* Commands */
- public static final int REGISTER = 0;
- public static final int POSITION = 1;
- public static final int CONNECT = 2;
- public static final int DISCONNECT = 3;
- public static final int NOTIFY = 4;
+ /* Main -> Task Messsages */
+ static enum Command {
+ REGISTER,
+ CONNECT,
+ DISCONNECT,
+ };
+
+ /* Task -> Main messages */
+ static enum Response {
+ POSITION,
+ NOTIFY,
+ };
/* Private data */
- private Messenger messenger;
- private Thread thread;
- private boolean active;
+ private Messenger messenger;
+ private IBeaconManager ibeacon;
/* Private methods */
- private void tellMain(int cmd, Object value)
+ private void tellMain(Response cmd, Object value)
{
try {
android.os.Message msg = android.os.Message.obtain();
- msg.what = cmd;
+ msg.what = cmd.ordinal();
msg.obj = value;
this.messenger.send(msg);
} catch (Exception e) {
private void notify(String text, int icon)
{
// Notify Main
- this.tellMain(NOTIFY, text);
+ this.tellMain(Task.Response.NOTIFY, text);
// Notification bar
//Notification note = new Notification(icon, null, 0);
//Intent intent = new Intent(this, Main.class);
//PendingIntent pend = PendingIntent.getActivity(this, 0, intent, 0);
-
//note.setLatestEventInfo(this, "iBeaconNav!", text, pend);
- //this.startForeground(1, note);
+ //PendingIntent pend = PendingIntent.getActivity(this, 0, intent, 0);
+
+ Notification note = new Notification.Builder(this)
+ .setContentTitle("iBeaconNav!")
+ .setContentText("iBeaconNav!")
+ .setSmallIcon(icon)
+ .build();
+
+ this.startForeground(1, note);
}
- private void handle(int cmd, Messenger mgr)
+ private void handle(Command cmd, Messenger mgr)
{
// Validate messenger
- if (cmd != REGISTER && mgr != null && mgr != this.messenger) {
+ if (cmd != Task.Command.REGISTER && mgr != null && mgr != this.messenger)
Util.debug("Task: handle - invalid messenger");
- }
-
- // Setup communication with Main
- if (cmd == REGISTER) {
- Util.debug("Task: handle - register");
- this.messenger = mgr;
- this.tellMain(REGISTER, this);
- }
-
- // Create client thread
- if (cmd == CONNECT && this.thread == null) {
- Util.debug("Task: handle - connect");
- this.thread = new Thread(this);
- this.thread.start();
- }
- // Stop client thread
- if (cmd == DISCONNECT && this.thread != null) {
- Util.debug("Task: handle - register");
- try {
- this.thread.join();
- } catch (Exception e) {
- Util.debug("Task: error stopping service", e);
- }
+ // Handle the command
+ switch (cmd) {
+ // Setup communication with Main
+ case REGISTER:
+ Util.debug("Task: handle - register");
+ this.messenger = mgr;
+ break;
+
+ // Create client thread
+ case CONNECT:
+ Util.debug("Task: handle - connect");
+ this.notify("Connected", android.R.drawable.presence_online);
+ this.ibeacon = IBeaconManager.getInstanceForApplication(this);
+ this.ibeacon.bind(this);
+ //this.ibeacon.setBackgroundMode(this, false);
+ break;
+
+ // Stop client thread
+ case DISCONNECT:
+ Util.debug("Task: handle - register");
+ //this.ibeacon.setBackgroundMode(this, true);
+ this.ibeacon.unBind(this);
+ this.ibeacon = null;
+ this.stopForeground(true);
+ break;
}
}
/* Public methods */
public boolean isRunning()
{
- return this.thread != null;
- }
-
- /* Runnable methods */
- @Override
- public void run()
- {
- Util.debug("Task: thread run");
-
- // Run nav algorithm
- while (this.active) {
- // Read sensor data
- this.tellMain(POSITION, 0);
- }
-
- Util.debug("Task: thread exit");
+ return this.ibeacon != null;
}
/* Service Methods */
{
Util.debug("Task: onCreate");
super.onCreate();
+ IBeaconManager.LOG_DEBUG = true;
}
@Override
public void onDestroy()
{
Util.debug("Task: onDestroy");
- this.handle(DISCONNECT, null);
+ super.onDestroy();
}
@Override
{
Util.debug("Task: onStartCommand");
int rval = super.onStartCommand(intent, flags, startId);
- int cmd = intent.getExtras().getInt("Command");
+ Command cmd = (Command)intent.getExtras().get("Command");
Messenger mgr = (Messenger)intent.getExtras().get("Messenger");
this.handle(cmd, mgr);
return rval;
Util.debug("Task: onBind");
return null;
}
+
+ /* IBeaconConsumer Methods */
+ @Override
+ public void onIBeaconServiceConnect() {
+ Util.debug("Task: onIBeaconServiceConnect");
+
+ this.ibeacon.setRangeNotifier(this);
+ this.ibeacon.setMonitorNotifier(this);
+
+ try {
+ Region region = new Region("iBeaconNavMonitoringId", null, null, null);
+ this.ibeacon.startRangingBeaconsInRegion(region);
+ this.ibeacon.startMonitoringBeaconsInRegion(region);
+ } catch (RemoteException e) {
+ Util.debug("Task: onIBeaconServiceConnect - error");
+ }
+ }
+
+ /* RangeNotifier Methods */
+ @Override
+ public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
+ Util.debug("Task: didRangeBeaconsInRegion");
+ }
+
+ /* MonitorNotifier Methods */
+ @Override
+ public void didEnterRegion(Region region) {
+ Util.debug("Task: didEnterRegion");
+ }
+
+ @Override
+ public void didExitRegion(Region region) {
+ Util.debug("Task: didExitRegion");
+ }
+
+ @Override
+ public void didDetermineStateForRegion(int state, Region region) {
+ Util.debug("Task: didDetermineStateForRegion");
+ }
}