1. 程式人生 > >Android Beacon 開發(IBeacon)

Android Beacon 開發(IBeacon)

iBeacon是蘋果公司2013年9月釋出的移動裝置用OS(ios7)上配備的新功能。其主要的工作方式就是:配備有低功耗藍芽

(BLE)通訊功能的裝置使用BLE技術向周圍傳送自己特有的ID。

這個網址對iBeacon進行了基本介紹,建議大家去閱讀一下:http://www.beaconsandwich.com/what-is-ibeacon.html

在2015年,谷歌釋出Eddystone,它其實類似於iBeacon。

對於這兩者的主要區別,大家可以瀏覽這個網址的內容:https://www.zhihu.com/question/32708729

本文的demo開發是基於github上的一個開源專案Altbeacon:

https://github.com/AltBeacon/android-beacon-library

Aitebeacon官方網站:http://altbeacon.github.io/android-beacon-library/

本文參照了:http://blog.csdn.net/wjskeepmaking/article/details/52067585

本文程式碼已上傳至CSDN:http://download.csdn.net/download/eueheuen/10212291

1,建立工程之後,在buid.gradle中匯入AltBeacon Library:

dependencies {
    implementation fileTree(dir
: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.0.2' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
//noinspection GradleDynamicVersion implementation 'org.altbeacon:android-beacon-library:2+' }

2,建立一個Application,這個Application需要實現一個介面:BootstrapNotifier:

public class MyApp extends Application implements BootstrapNotifier {
    private RegionBootstrap regionBootstrap;
    private BackgroundPowerSaver backgroundPowerSaver;
    @Override
    public void onCreate() {
        super.onCreate();

        BeaconManager beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
        beaconManager.getBeaconParsers().clear();
        beaconManager.getBeaconParsers().add(new BeaconParser()
                .setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
        Region region = new Region("all-region-beacon",null,null,null);
        regionBootstrap = new RegionBootstrap(this,region);
        backgroundPowerSaver = new BackgroundPowerSaver(this);

    }

    @Override
    public void didEnterRegion(Region region) {

    }

    @Override
    public void didExitRegion(Region region) {

    }

    @Override
    public void didDetermineStateForRegion(int i, Region region) {

    }
}

3,新增相關許可權:

<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<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" />

4,建立Service:

public class BeaconService extends Service implements BeaconConsumer, RangeNotifier {

    //單位:毫秒
    //後臺掃描
    private static final long DEFAULT_BACKGROUND_SCAN_PERIOD = 1000L;
    private static final long DEFAULT_BACKGROUND_BETWEEN_SCAN_PERIOD = 0L;

    //前臺掃描
    private static final long DEFAULT_SCAN_PERIOD = 1000L;
    private static final long DEFAULT_BETWEEN_SCAN_PERIOD = 500L;

    private BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
    private MyBR myBR;

    public BeaconService() {

    }

    @Override
    public void onCreate() {
        super.onCreate();
        initBeacon();
        beaconManager.bind(this);

        myBR = new MyBR();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("");
        registerReceiver(myBR,intentFilter);

    }

    private void initBeacon() {
        //設定前臺掃描時長
        beaconManager.setForegroundScanPeriod(DEFAULT_SCAN_PERIOD);
        //設定前臺掃描間隔
        beaconManager.setForegroundBetweenScanPeriod(DEFAULT_BETWEEN_SCAN_PERIOD);
        //設定每個藍芽LE掃描週期的持續時間(以毫秒為單位)以查詢信標。
        // 此函式用於設定呼叫bind(org.altbeacon.beacon.BeaconConsumer)之前的時間段或在背景/前景之間切換的時間段。
        // 要使其在已經執行的掃描(在下一個週期開始時)生效,請呼叫updateScanPeriods()
        //設定後臺掃描時長
        beaconManager.setBackgroundScanPeriod(DEFAULT_BACKGROUND_SCAN_PERIOD);

        //當沒有測距/監控客戶端位於前臺時,設定每個藍芽LE掃描週期之間不掃描的時間(以毫秒為單位)
        //設定後臺掃描間隔
        beaconManager.setBackgroundBetweenScanPeriod(DEFAULT_BACKGROUND_BETWEEN_SCAN_PERIOD);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (beaconManager != null){
            beaconManager.removeRangeNotifier(this);
        }
        if (myBR!= null){
            unregisterReceiver(myBR);
            Toast.makeText(this,"完犢子了",Toast.LENGTH_SHORT).show();
            Log.d("MyBeaconNum","完犢子了");
        }

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public void onBeaconServiceConnect() {

        Region region = new Region("all-region-beacon", null, null, null);
        beaconManager.addRangeNotifier(this);
        try {
            beaconManager.startRangingBeaconsInRegion(region);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
        List<Beacon> beacons = new ArrayList<>();
        for (Beacon beacon : collection) {
            beacons.add(beacon);
        }

        Log.d("MyBeaconNum",beacons.size()+"");

        Intent intent = new Intent(MainActivity.BEACON_ACTION);
        intent.putParcelableArrayListExtra("beacon", (ArrayList<? extends Parcelable>) beacons);//因為Beacon繼承了Parcelable,
        sendBroadcast(intent);
    }

    class MyBR extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            stopSelf();
        }
    }
}

5,不要忘記在Manifest中註冊Service:

<service
    android:name=".BeaconService"
    android:enabled="true"
    android:exported="true"
    tools:replace="android:exported"
    android:isolatedProcess="false"
    android:label="beacon" >
</service>

6,MainActivity:

public class MainActivity extends AppCompatActivity {
    private BeaconBroadcastReceiver beaconBroadcastReceiver;
    private static final String TAG = "MyTAG";
    public static final String BEACON_ACTION = "com.example.lenovo.mybeaconlib";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        beaconBroadcastReceiver = new BeaconBroadcastReceiver();
        Intent intent = new Intent(MainActivity.this, BeaconService.class);
        startService(intent);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //停止服務
        Intent intent=new Intent("PleaseStopService");
        sendBroadcast(intent);

        if (beaconBroadcastReceiver != null){
            try{
                unregisterReceiver(beaconBroadcastReceiver);
            }catch (Throwable ignored){
                
            }
           
        }

    }

    @Override
    protected void onResume() {
        super.onResume();
        registerReceiver(beaconBroadcastReceiver, getBeaconIntentFilter());
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (beaconBroadcastReceiver != null){
            unregisterReceiver(beaconBroadcastReceiver);
        }

    }

    class BeaconBroadcastReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BEACON_ACTION.equals(action)) {
                List<Beacon> beacons = intent.getParcelableArrayListExtra("beacon");
                Log.i(TAG, "onReceive: "+ beacons.size());
                for (Beacon beacon : beacons){

                    //獲取 uuid,major,minor
                    String uuid = String.valueOf(beacon.getId1());
                    String major = String.valueOf(beacon.getId2());
                    String mMinor = String.valueOf(beacon.getId3());
                    int minor = Integer.parseInt(mMinor);

                    String text = "uuid: " + beacon.getServiceUuid() + "\r\n" +
                            "dis: " + beacon.getDistance() + "m" + "\r\n" +
                            "BluetoothName: " + beacon.getBluetoothName() + "\r\n" +
                            "BluetoothAddress: " +  beacon.getBluetoothAddress() + "\r\n" +
                            "ParserIdentifier(分析器識別符號): " +  beacon.getParserIdentifier() + "\r\n" +
                            "BeaconTypeCode: " +  beacon.getBeaconTypeCode() + "\r\n" +
                            "Rssi: " +  beacon.getRssi() + "\r\n" +
                            "RunningAverageRssi:"+beacon.getRunningAverageRssi() + "\r\n" +
                            "TxPower: " +  beacon.getTxPower() + "\r\n" +
                            "ExtraDataFields:"+beacon.getExtraDataFields() +"\r\n" +
                            "DataFields:"+beacon.getDataFields()+"\r\n" +
                            "BeaconToString:"+beacon.toString();

                    Log.i(TAG, "onReceive: "+ text);

                }
                Log.i(TAG, "onReceive: "+ "**********************************");
            }
        }
    }

    IntentFilter getBeaconIntentFilter() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BEACON_ACTION);
        return intentFilter;
    }

}