Last active
June 6, 2020 19:55
-
-
Save epsi95/a0c49c065494d4399f3e20999b7e5059 to your computer and use it in GitHub Desktop.
BeaconReferenceApplication.java Adaptation for Foreground Scan and Broadcast
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.altbeacon.beaconreference; | |
import android.app.Application; | |
import android.app.Notification; | |
import android.app.NotificationChannel; | |
import android.app.NotificationManager; | |
import android.app.PendingIntent; | |
import android.app.TaskStackBuilder; | |
import android.content.Context; | |
import android.content.Intent; | |
import androidx.core.app.NotificationCompat; | |
import android.os.Build; | |
import android.util.Log; | |
import org.altbeacon.beacon.Beacon; | |
import org.altbeacon.beacon.BeaconManager; | |
import org.altbeacon.beacon.BeaconParser; | |
import org.altbeacon.beacon.BeaconTransmitter; | |
import org.altbeacon.beacon.Region; | |
import org.altbeacon.beacon.TimedBeaconSimulator; | |
import org.altbeacon.beacon.powersave.BackgroundPowerSaver; | |
import org.altbeacon.beacon.startup.RegionBootstrap; | |
import org.altbeacon.beacon.startup.BootstrapNotifier; | |
import java.util.Arrays; | |
/** | |
* Created by dyoung on 12/13/13. | |
*/ | |
public class BeaconReferenceApplication extends Application implements BootstrapNotifier { | |
private static final String TAG = "BeaconReferenceApp"; | |
private RegionBootstrap regionBootstrap; | |
private BackgroundPowerSaver backgroundPowerSaver; | |
private boolean haveDetectedBeaconsSinceBoot = false; | |
private MonitoringActivity monitoringActivity = null; | |
private String cumulativeLog = ""; | |
public void onCreate() { | |
super.onCreate(); | |
BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this); | |
// By default the AndroidBeaconLibrary will only find AltBeacons. If you wish to make it | |
// find a different type of beacon, you must specify the byte layout for that beacon's | |
// advertisement with a line like below. The example shows how to find a beacon with the | |
// same byte layout as AltBeacon but with a beaconTypeCode of 0xaabb. To find the proper | |
// layout expression for other beacon types, do a web search for "setBeaconLayout" | |
// including the quotes. | |
// | |
beaconManager.getBeaconParsers().clear(); | |
beaconManager.getBeaconParsers().add(new BeaconParser(). | |
setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24")); | |
beaconManager.setDebug(true); | |
// Uncomment the code below to use a foreground service to scan for beacons. This unlocks | |
// the ability to continually scan for long periods of time in the background on Andorid 8+ | |
// in exchange for showing an icon at the top of the screen and a always-on notification to | |
// communicate to users that your app is using resources in the background. | |
// | |
Notification.Builder builder = new Notification.Builder(this); | |
builder.setSmallIcon(R.drawable.ic_launcher); | |
builder.setContentTitle("Scanning for Beacons"); | |
Intent intent = new Intent(this, MonitoringActivity.class); | |
PendingIntent pendingIntent = PendingIntent.getActivity( | |
this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | |
); | |
builder.setContentIntent(pendingIntent); | |
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | |
NotificationChannel channel = new NotificationChannel("My Notification Channel ID", | |
"My Notification Name", NotificationManager.IMPORTANCE_DEFAULT); | |
channel.setDescription("My Notification Channel Description"); | |
NotificationManager notificationManager = (NotificationManager) getSystemService( | |
Context.NOTIFICATION_SERVICE); | |
notificationManager.createNotificationChannel(channel); | |
builder.setChannelId(channel.getId()); | |
} | |
beaconManager.enableForegroundServiceScanning(builder.build(), 456); | |
// For the above foreground scanning service to be useful, you need to disable | |
// JobScheduler-based scans (used on Android 8+) and set a fast background scan | |
// cycle that would otherwise be disallowed by the operating system. | |
// | |
beaconManager.setEnableScheduledScanJobs(false); | |
beaconManager.setBackgroundBetweenScanPeriod(10000); | |
beaconManager.setBackgroundScanPeriod(1100); | |
Beacon beacon = new Beacon.Builder() | |
.setId1("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6") | |
.setId2("1") | |
.setId3("2") | |
.setManufacturer(0x0118) | |
.setTxPower(-59) | |
.setDataFields(Arrays.asList(new Long[] {0l})) | |
.build(); | |
BeaconParser beaconParser = new BeaconParser() | |
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"); | |
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getApplicationContext(), beaconParser); | |
beaconTransmitter.startAdvertising(beacon); | |
Log.d(TAG, "setting up background monitoring for beacons and power saving"); | |
// wake up the app when a beacon is seen | |
Region region = new Region("backgroundRegion", | |
null, null, null); | |
regionBootstrap = new RegionBootstrap(this, region); | |
// simply constructing this class and holding a reference to it in your custom Application | |
// class will automatically cause the BeaconLibrary to save battery whenever the application | |
// is not visible. This reduces bluetooth power usage by about 60% | |
backgroundPowerSaver = new BackgroundPowerSaver(this); | |
// If you wish to test beacon detection in the Android Emulator, you can use code like this: | |
// BeaconManager.setBeaconSimulator(new TimedBeaconSimulator() ); | |
// ((TimedBeaconSimulator) BeaconManager.getBeaconSimulator()).createTimedSimulatedBeacons(); | |
} | |
public void disableMonitoring() { | |
if (regionBootstrap != null) { | |
regionBootstrap.disable(); | |
regionBootstrap = null; | |
} | |
} | |
public void enableMonitoring() { | |
Region region = new Region("backgroundRegion", | |
null, null, null); | |
regionBootstrap = new RegionBootstrap(this, region); | |
} | |
@Override | |
public void didEnterRegion(Region arg0) { | |
// In this example, this class sends a notification to the user whenever a Beacon | |
// matching a Region (defined above) are first seen. | |
Log.d(TAG, "did enter region."); | |
if (!haveDetectedBeaconsSinceBoot) { | |
Log.d(TAG, "auto launching MainActivity"); | |
// The very first time since boot that we detect an beacon, we launch the | |
// MainActivity | |
Intent intent = new Intent(this, MonitoringActivity.class); | |
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
// Important: make sure to add android:launchMode="singleInstance" in the manifest | |
// to keep multiple copies of this activity from getting created if the user has | |
// already manually launched the app. | |
this.startActivity(intent); | |
haveDetectedBeaconsSinceBoot = true; | |
} else { | |
if (monitoringActivity != null) { | |
// If the Monitoring Activity is visible, we log info about the beacons we have | |
// seen on its display | |
logToDisplay("I see a beacon again" ); | |
} else { | |
// If we have already seen beacons before, but the monitoring activity is not in | |
// the foreground, we send a notification to the user on subsequent detections. | |
Log.d(TAG, "Sending notification."); | |
sendNotification(); | |
} | |
} | |
} | |
@Override | |
public void didExitRegion(Region region) { | |
logToDisplay("I no longer see a beacon."); | |
} | |
@Override | |
public void didDetermineStateForRegion(int state, Region region) { | |
logToDisplay("Current region state is: " + (state == 1 ? "INSIDE" : "OUTSIDE ("+state+")")); | |
} | |
private void sendNotification() { | |
NotificationCompat.Builder builder = | |
new NotificationCompat.Builder(this) | |
.setContentTitle("Beacon Reference Application") | |
.setContentText("An beacon is nearby.") | |
.setSmallIcon(R.drawable.ic_launcher); | |
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this); | |
stackBuilder.addNextIntent(new Intent(this, MonitoringActivity.class)); | |
PendingIntent resultPendingIntent = | |
stackBuilder.getPendingIntent( | |
0, | |
PendingIntent.FLAG_UPDATE_CURRENT | |
); | |
builder.setContentIntent(resultPendingIntent); | |
NotificationManager notificationManager = | |
(NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); | |
notificationManager.notify(1, builder.build()); | |
} | |
public void setMonitoringActivity(MonitoringActivity activity) { | |
this.monitoringActivity = activity; | |
} | |
private void logToDisplay(String line) { | |
cumulativeLog += (line + "\n"); | |
if (this.monitoringActivity != null) { | |
this.monitoringActivity.updateLog(cumulativeLog); | |
} | |
} | |
public String getLog() { | |
return cumulativeLog; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment