package com.mingle.myapplication.service;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.mingle.myapplication.activity.MainActivity;
import com.mingle.myapplication.R;
import com.mingle.myapplication.activity.ShowMsgActivity;
import com.mingle.myapplication.model.SharedPreferenceUtil;
import com.perples.recosdk.RECOBeacon;
import com.perples.recosdk.RECOBeaconManager;
import com.perples.recosdk.RECOBeaconRegion;
import com.perples.recosdk.RECOBeaconRegionState;
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 RECOMonitoringListener, RECORangingListener, RECOServiceConnectListener {
private long mScanDuration = 1*1000L;
private long mSleepDuration = 1*1000L;
private long mRegionExpirationTime = 1*1000L;
private int mNotificationID = 9999;
private int mNotificationID2 = 0;
private RECOBeaconManager mRecoManager;
private ArrayList<RECOBeaconRegion> mRegions;
private ArrayList<RECOBeacon> mRangedBeacons;
@Override
public void onCreate() {
//Log.i("RECOBackgroundRangingService", "onCreate()");
super.onCreate();
/**
* Create an instance of RECOBeaconManager (to set ranging timeout in the background.)
* If you do not want to set ranging timeout in the backgournd, create an instance:
* mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), false);
* WARNING: It will affect the battery consumption.
*
* RECOBeaconManager 인스턴스틀 생성합니다. (백그라운드 ranging timeout 설정)
* 백그라운드 ranging timeout을 설정하고 싶지 않으시다면, 다음과 같이 생성하시기 바랍니다.
* mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), false);
* 주의: false로 설정 시, 배터리 소모량이 증가합니다.
*/
mRecoManager = RECOBeaconManager.getInstance(getApplicationContext(), false);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("RECO_BRS", "onStartCommand");
this.bindRECOService();
return START_STICKY;
}
@Override
public void onDestroy() {
//Log.i("RECOBackgroundRangingService", "onDestroy()");
this.tearDown();
super.onDestroy();
}
@Override
public void onTaskRemoved(Intent rootIntent) {
//Log.i("RECOBackgroundRangingService", "onTaskRemoved()");
super.onTaskRemoved(rootIntent);
}
private void bindRECOService() {
//Log.i("RECOBackgroundRangingService", "bindRECOService()");
mRegions = new ArrayList<RECOBeaconRegion>();
this.generateBeaconRegion();
mRecoManager.setMonitoringListener(this);
mRecoManager.setRangingListener(this);
mRecoManager.bind(this);
}
private void generateBeaconRegion() {
//Log.i("RECOBackgroundRangingService", "generateBeaconRegion()");
RECOBeaconRegion recoRegion;
recoRegion = new RECOBeaconRegion(MainActivity.RECO_UUID, "RECO Sample Region");
recoRegion.setRegionExpirationTimeMillis(this.mRegionExpirationTime);
mRegions.add(recoRegion);
}
private void startMonitoring() {
//Log.i("RECOBackgroundRangingService", "startMonitoring()");
mRecoManager.setScanPeriod(this.mScanDuration);
mRecoManager.setSleepPeriod(this.mSleepDuration);
for(RECOBeaconRegion region : mRegions) {
try {
mRecoManager.startMonitoringForRegion(region);
} catch (RemoteException e) {
// Log.e("RECOBackgroundRangingService", "RemoteException has occured while executing RECOManager.startMonitoringForRegion()");
e.printStackTrace();
} catch (NullPointerException e) {
// Log.e("RECOBackgroundRangingService", "NullPointerException has occured while executing RECOManager.startMonitoringForRegion()");
e.printStackTrace();
}
}
}
private void stopMonitoring() {
//Log.i("RECOBackgroundRangingService", "stopMonitoring()");
for(RECOBeaconRegion region : mRegions) {
try {
mRecoManager.stopMonitoringForRegion(region);
} catch (RemoteException e) {
//Log.e("RECOBackgroundRangingService", "RemoteException has occured while executing RECOManager.stopMonitoringForRegion()");
e.printStackTrace();
} catch (NullPointerException e) {
//Log.e("RECOBackgroundRangingService", "NullPointerException has occured while executing RECOManager.stopMonitoringForRegion()");
e.printStackTrace();
}
}
}
private void startRangingWithRegion(RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "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("RECOBackgroundRangingService", "RemoteException has occured while executing RECOManager.startRangingBeaconsInRegion()");
e.printStackTrace();
} catch (NullPointerException e) {
//Log.e("RECOBackgroundRangingService", "NullPointerException has occured while executing RECOManager.startRangingBeaconsInRegion()");
e.printStackTrace();
}
}
private void stopRangingWithRegion(RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "stopRangingWithRegion()");
try {
mRecoManager.stopRangingBeaconsInRegion(region);
} catch (RemoteException e) {
//Log.e("RECOBackgroundRangingService", "RemoteException has occured while executing RECOManager.stopRangingBeaconsInRegion()");
e.printStackTrace();
} catch (NullPointerException e) {
//Log.e("RECOBackgroundRangingService", "NullPointerException has occured while executing RECOManager.stopRangingBeaconsInRegion()");
e.printStackTrace();
}
}
private void tearDown() {
//Log.i("RECOBackgroundRangingService", "tearDown()");
this.stopMonitoring();
try {
mRecoManager.unbind();
} catch (RemoteException e) {
//Log.e("RECOBackgroundRangingService", "RemoteException has occured while executing unbind()");
e.printStackTrace();
}
}
@Override
public void onServiceConnect() {
//Log.i("RECOBackgroundRangingService", "onServiceConnect()");
this.startMonitoring();
//Write the code when RECOBeaconManager is bound to RECOBeaconService
}
@Override
public void didDetermineStateForRegion(RECOBeaconRegionState state, RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "didDetermineStateForRegion()");
//Write the code when the state of the monitored region is changed
}
@Override
public void didEnterRegion(RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "didEnterRegion() - " + region.getUniqueIdentifier());
this.popupNotification("Ranging Inside of " + region.getUniqueIdentifier());
//Write the code when the device is enter the region
SharedPreferenceUtil.putSharedPreference(getApplicationContext(), "ISRESIONSET", 1);
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
//Intent intent = new Intent(getApplicationContext(), ShowMsgActivity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//getApplicationContext().startActivity(intent);
}
@Override
public void didExitRegion(RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "didExitRegion() - " + region.getUniqueIdentifier());
this.popupNotification("Ranging Outside of " + region.getUniqueIdentifier());
//Write the code when the device is exit the region
SharedPreferenceUtil.putSharedPreference(getApplicationContext(), "ISRESIONSET", 0);
this.stopRangingWithRegion(region); //stop ranging because the device is outside of the region from now
}
@Override
public void didStartMonitoringForRegion(RECOBeaconRegion region) {
//Log.i("RECOBackgroundRangingService", "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("RECOBackgroundRangingService", "didRangeBeaconsInRegion() - " + region.getUniqueIdentifier() + " with " + beacons.size() + " beacons");
//Write the code when the beacons inside of the region is received
updateAllBeacons(beacons);
double selectBeacon=10.0f;
int selectBeaconMajor=0;
try {
for(int i=0;i<beacons.size();i++) {
RECOBeacon recoBeacon = mRangedBeacons.get(i);
if(selectBeacon > recoBeacon.getAccuracy()) {
selectBeacon = recoBeacon.getAccuracy();
selectBeaconMajor = recoBeacon.getMajor();
}
}
SharedPreferenceUtil.putSharedPreference(getApplicationContext(), "ResionMajor", selectBeaconMajor);
Log.d("RangeBeaconsInRegion ", "resion Major: " + selectBeaconMajor);
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
}
public void updateAllBeacons(Collection<RECOBeacon> beacons) {
synchronized (beacons) {
mRangedBeacons = new ArrayList<RECOBeacon>(beacons);
}
}
private void popupNotification(String msg) {
//Log.i("RECOBackgroundRangingService", "popupNotification()");
String currentTime = new SimpleDateFormat("HH:mm:ss", Locale.KOREA).format(new Date());
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification.Builder builder = new Notification.Builder(this).setSmallIcon(R.mipmap.ic_cocktail)
.setContentTitle(msg + " " + currentTime)
.setContentText(msg);
Notification.InboxStyle inboxStyle = new Notification.InboxStyle();
builder.setStyle(inboxStyle);
nm.cancel(mNotificationID2);
nm.notify(mNotificationID, builder.build());
mNotificationID2 = mNotificationID;
mNotificationID = (mNotificationID - 1) % 1000 + 9000;
if(mNotificationID < 1) mNotificationID = 9999;
}
@Override
public IBinder onBind(Intent intent) {
//This method is not used
return null;
}
}