Java tutorial
/** * The MIT License (MIT) * * Copyright (c) 2014-2015 Perples, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.a3did.partner.recosample; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; import android.support.v4.app.NotificationCompat; import android.util.Log; import com.a3did.partner.partner.R; import com.perples.recosdk.RECOBeacon; import com.perples.recosdk.RECOBeaconManager; import com.perples.recosdk.RECOBeaconRegion; import com.perples.recosdk.RECOBeaconRegionState; import com.perples.recosdk.RECOErrorCode; import com.perples.recosdk.RECOMonitoringListener; import com.perples.recosdk.RECORangingListener; import com.perples.recosdk.RECOServiceConnectListener; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Locale; /** * RECOBackgroundRangingService is to monitor regions and range regions when the device is inside in the BACKGROUND. * * RECOBackgroundMonitoringService ?? monitoring? , region ? ?? ranging? . */ public class RecoBackgroundRangingService extends Service implements RECORangingListener, RECOMonitoringListener, RECOServiceConnectListener { /** * We recommend 1 second for scanning, 10 seconds interval between scanning, and 60 seconds for region expiration time. * 1 , 10 , 60? region expiration time? . */ private long mScanDuration = 1 * 1000L; private long mSleepDuration = 1 * 1000L; private long mRegionExpirationTime = 60 * 1000L; private int mNotificationID = 9999; private RECOBeaconManager mRecoManager; private ArrayList<RECOBeaconRegion> mRegions; @Override public void onCreate() { Log.i("BackRangingService", "onCreate()"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("BackRangingService", "onStartCommand"); /** * Create an instance of RECOBeaconManager (to set scanning target and ranging timeout in the background.) * If you want to scan only RECO, and do not set ranging timeout in the backgournd, create an instance: * mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), true, false); * WARNING: False enableRangingTimeout will affect the battery consumption. * * RECOBeaconManager ? ?. ( ? ? ? ranging timeout ) * RECO? , ? ranging timeout? , ? ? ? ?. * mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), true, false); * ?: enableRangingTimeout? false , ? ?. */ mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), MainActivity.SCAN_RECO_ONLY, MainActivity.ENABLE_BACKGROUND_RANGING_TIMEOUT); this.bindRECOService(); return START_STICKY; } @Override public void onDestroy() { Log.i("BackRangingService", "onDestroy()"); this.tearDown(); super.onDestroy(); } @Override public void onTaskRemoved(Intent rootIntent) { Log.i("BackRangingService", "onTaskRemoved()"); super.onTaskRemoved(rootIntent); } private void bindRECOService() { Log.i("BackRangingService", "bindRECOService()"); mRegions = new ArrayList<RECOBeaconRegion>(); this.generateBeaconRegion(); mRecoManager.setMonitoringListener(this); mRecoManager.setRangingListener(this); mRecoManager.bind(this); } private void generateBeaconRegion() { Log.i("BackRangingService", "generateBeaconRegion()"); RECOBeaconRegion recoRegion; recoRegion = new RECOBeaconRegion(MainActivity.RECO_UUID, "RECO Sample Region"); recoRegion.setRegionExpirationTimeMillis(this.mRegionExpirationTime); mRegions.add(recoRegion); } private void startMonitoring() { Log.i("BackRangingService", "startMonitoring()"); mRecoManager.setScanPeriod(this.mScanDuration); mRecoManager.setSleepPeriod(this.mSleepDuration); for (RECOBeaconRegion region : mRegions) { try { mRecoManager.startMonitoringForRegion(region); } catch (RemoteException e) { Log.e("BackRangingService", "RemoteException has occured while executing RECOManager.startMonitoringForRegion()"); e.printStackTrace(); } catch (NullPointerException e) { Log.e("BackRangingService", "NullPointerException has occured while executing RECOManager.startMonitoringForRegion()"); e.printStackTrace(); } } } private void stopMonitoring() { Log.i("BackRangingService", "stopMonitoring()"); for (RECOBeaconRegion region : mRegions) { try { mRecoManager.stopMonitoringForRegion(region); } catch (RemoteException e) { Log.e("BackRangingService", "RemoteException has occured while executing RECOManager.stopMonitoringForRegion()"); e.printStackTrace(); } catch (NullPointerException e) { Log.e("BackRangingService", "NullPointerException has occured while executing RECOManager.stopMonitoringForRegion()"); e.printStackTrace(); } } } private void startRangingWithRegion(RECOBeaconRegion region) { Log.i("BackRangingService", "startRangingWithRegion()"); /** * There is a known android bug that some android devices scan BLE devices only once. (link: http://code.google.com/p/android/issues/detail?id=65863) * To resolve the bug in our SDK, you can use setDiscontinuousScan() method of the RECOBeaconManager. * This method is to set whether the device scans BLE devices continuously or discontinuously. * The default is set as FALSE. Please set TRUE only for specific devices. * * mRecoManager.setDiscontinuousScan(true); */ try { mRecoManager.startRangingBeaconsInRegion(region); } catch (RemoteException e) { Log.e("BackRangingService", "RemoteException has occured while executing RECOManager.startRangingBeaconsInRegion()"); e.printStackTrace(); } catch (NullPointerException e) { Log.e("BackRangingService", "NullPointerException has occured while executing RECOManager.startRangingBeaconsInRegion()"); e.printStackTrace(); } } private void stopRangingWithRegion(RECOBeaconRegion region) { Log.i("BackRangingService", "stopRangingWithRegion()"); try { mRecoManager.stopRangingBeaconsInRegion(region); } catch (RemoteException e) { Log.e("BackRangingService", "RemoteException has occured while executing RECOManager.stopRangingBeaconsInRegion()"); e.printStackTrace(); } catch (NullPointerException e) { Log.e("BackRangingService", "NullPointerException has occured while executing RECOManager.stopRangingBeaconsInRegion()"); e.printStackTrace(); } } private void tearDown() { Log.i("BackRangingService", "tearDown()"); this.stopMonitoring(); try { mRecoManager.unbind(); } catch (RemoteException e) { Log.e("BackRangingService", "RemoteException has occured while executing unbind()"); e.printStackTrace(); } } @Override public void onServiceConnect() { Log.i("BackRangingService", "onServiceConnect()"); this.startMonitoring(); //Write the code when RECOBeaconManager is bound to RECOBeaconService } @Override public void didDetermineStateForRegion(RECOBeaconRegionState state, RECOBeaconRegion region) { Log.i("BackRangingService", "didDetermineStateForRegion()"); //Write the code when the state of the monitored region is changed } @Override public void didEnterRegion(RECOBeaconRegion region, Collection<RECOBeacon> beacons) { /** * For the first run, this callback method will not be called. * Please check the state of the region using didDetermineStateForRegion() callback method. * * , ? ? . * didDetermineStateForRegion() region ? ? . */ //Get the region and found beacon list in the entered region Log.i("BackRangingService", "didEnterRegion() - " + region.getUniqueIdentifier()); this.popupNotification("Inside of " + region.getUniqueIdentifier()); //Write the code when the device is enter the region this.startRangingWithRegion(region); //start ranging to get beacons inside of the region //from now, stop ranging after 10 seconds if the device is not exited } @Override public void didExitRegion(RECOBeaconRegion region) { /** * For the first run, this callback method will not be called. * Please check the state of the region using didDetermineStateForRegion() callback method. * * , ? ? . * didDetermineStateForRegion() region ? ? . */ Log.i("BackRangingService", "didExitRegion() - " + region.getUniqueIdentifier()); this.popupNotification("Outside of " + region.getUniqueIdentifier()); //Write the code when the device is exit the region this.stopRangingWithRegion(region); //stop ranging because the device is outside of the region from now } @Override public void didStartMonitoringForRegion(RECOBeaconRegion region) { Log.i("BackRangingService", "didStartMonitoringForRegion() - " + region.getUniqueIdentifier()); //Write the code when starting monitoring the region is started successfully } @Override public void didRangeBeaconsInRegion(Collection<RECOBeacon> beacons, RECOBeaconRegion region) { Log.i("BackRangingService", "didRangeBeaconsInRegion() - " + region.getUniqueIdentifier() + " with " + beacons.size() + " beacons"); //Write the code when the beacons inside of the region is received } private void popupNotification(String msg) { Log.i("BackRangingService", "popupNotification()"); String currentTime = new SimpleDateFormat("HH:mm:ss", Locale.KOREA).format(new Date()); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); NotificationCompat.Builder builder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_launcher).setContentTitle(msg + " " + currentTime).setContentText(msg); NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); builder.setStyle(inboxStyle); nm.notify(mNotificationID, builder.build()); mNotificationID = (mNotificationID - 1) % 1000 + 9000; } @Override public IBinder onBind(Intent intent) { //This method is not used return null; } @Override public void onServiceFail(RECOErrorCode errorCode) { //Write the code when the RECOBeaconService is failed. //See the RECOErrorCode in the documents. return; } @Override public void monitoringDidFailForRegion(RECOBeaconRegion region, RECOErrorCode errorCode) { //Write the code when the RECOBeaconService is failed to monitor the region. //See the RECOErrorCode in the documents. return; } @Override public void rangingBeaconsDidFailForRegion(RECOBeaconRegion region, RECOErrorCode errorCode) { //Write the code when the RECOBeaconService is failed to range beacons in the region. //See the RECOErrorCode in the documents. return; } }