检测到信标后在后台启动应用程序

Start an app in the background after detecting beacon

所以有一个 class 扩展应用程序并实现 BootstrapNotifier 和在后台运行的 RangeNotifier。当应用程序首次打开时它工作正常并且可以很好地检测到信标和信标的信息但是现在需要它在设备(tablet/phone)打开时在后台自动启动并且当应用程序仍然关闭时继续在后台搜索信标。

有一个名为 postService.Post 的 AsyncTask,我在其中调用特定的 Activitie,如下所示

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        //to return a url(test example was a youtube url from db->https://www.youtube.com

        if(jsonStr==null){

        }
        else{
            //Log.d("URL",resultStr);
            /*
            Log.d("description",description);
            Log.d("title",title);
            Log.d("image",image);
            */
            Context context_onPosExecute = c;//getApplicationContext();
            Intent intent = new Intent(context_onPosExecute, Service.class);
            //intent.putExtra("json", resultStr.toString());
            //intent.putExtra("url", resultStr);
            intent.putExtra("description", description);
            intent.putExtra("title", title);
            intent.putExtra("image", image);

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            c.startActivity(intent);

            //resultStr = "";

        }
    }

此代码用于检测到信标的背景,并在检测到信标时调用 postService.Post 启动 Activitie。

@Override
>     public void onCreate() {
>         super.onCreate();
>     
>         //Movetasktoback(true);
>     
>         //turn on/enable the bluetooth
>         if(MainActivity.mBluetoothAdapter == null) {
>             MainActivity.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
>         }
>         if (!MainActivity.mBluetoothAdapter.isEnabled()) {
>             MainActivity.mBluetoothAdapter.enable();
>         }
>     
>     
>         // Simply constructing this class and holding a reference to it in your custom Application class
>         // enables auto battery saving of about 60%
>         //private BackgroundPowerSaver backgroundPowerSaver;//to able battery saving
>         //backgroundPowerSaver = new BackgroundPowerSaver(this);
>         beaconManager = BeaconManager.getInstanceForApplication(this);
>         Region region = new Region(".Background", Identifier.parse(UUID),null,null);//
> Identifier.parse(UUID),Identifier.parse("1") ,Identifier.parse("1"));
>         //beaconManager.setDebug(true);
>         try{
>             // set the duration of the scan to be 1.1 seconds
>             beaconManager.setBackgroundScanPeriod(1100l);
>             // set the time between each scan to be 1 hour (3600 seconds)//50000l
>             //60 seconds change after seing if more time still catchs the beacon to improve battery saving
>             beaconManager.setBackgroundBetweenScanPeriod(60000l);//3600000l
>             beaconManager.updateScanPeriods();
>     
>         }  catch (RemoteException e) {
>             //Log.e(TAG, "Cannot talk to service");
>         }
>         //beaconManager.getBetweenScanPeriod();
>         // wake up the app when any beacon is seen (you can specify specific id filers in the parameters below)
>         regionBootstrap = new RegionBootstrap(this, region);
>     
>     
>         //beaconManager.setMonitorNotifier(this);
>         //beaconManager.setBackgroundMode(true);
>         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"));
>         beaconManager.setRangeNotifier(this);
>     
>     
>     }
>     
>     public class Background extends Application implements BootstrapNotifier,RangeNotifier
>     
>     @Override
>     public void didEnterRegion(Region region) {
>         //Log.d(TAG, "Got a didEnterRegion call uuid->"+region.getId1());
>     
>         try {
>             Log.d(TAG,"calling startRangingBeaconsInRegion");
>             beaconManager.startRangingBeaconsInRegion(region);
>         }
>         catch (RemoteException e) {
>             Log.d(TAG, "Can't start ranging");
>         }
>     
>         // This call to disable will make it so the activity below only gets launched the first time a beacon is seen (until the next
> time the app is launched)
>         // if you want the Activity to launch every single time beacons come into view, remove this call.
>         //regionBootstrap.disable();
>         /*
>         Intent intent = new Intent(this, MainActivity.class);
>         // IMPORTANT: in the AndroidManifest.xml definition of this activity, you must set android:launchMode="singleInstance" or you will
> get two instances
>         // created when a user launches the activity manually and it gets launched from here.
>         //get the information about the beacon detected that is the UUID(getId1()), MAJOR(getId2()) and MINOR(getId3())
>         //and send that to the main activity that will do the request of the backoffice(and see if for the beacon detected there is any in
> the db
>         // and if there is will get the url camp that will call s service)
>         //intent.putExtra("uuid",region.getId1().toString());
>         //intent.putExtra("major",region.getId2().toString());
>         //intent.putExtra("minor",region.getId3().toString());
>         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
>         this.startActivity(intent);
>         */
>     }
>     
>      @Override
>     public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
>         Log.d(TAG, "entered the range beacons");
>         if (beacons.size() > 0) {
>             for(Beacon beacon: beacons){
>                 Log.d(TAG, "Beacon detected with id1: " + beacon.getId1() + " id2:" + beacon.getId2() + " id3: " +
> beacon.getId3() + " distance: " + beacon.getDistance());
>                 String uuid = beacon.getId1().toString();
>                 String major = beacon.getId2().toString();
>                 String minor = beacon.getId3().toString();
>     
>                 //call a service in backoffice to retrive the url associated to this 3 ids
>                 //url for the request of the service http://localhost/mobishout-admin/services/?q={%22Beacon_getUrl%22:{%22uuid%22:%22EBEFD08370A247C89837E7B5634DF524%22,%22major%22:%221%22,%22minor%22:%221%22}}
>                 PostService postService = new PostService();
>                 //pass uuid without the - between and case because of the format that will be insert in the db is different of the obtain of
> the beacon
>                 uuid = uuid.replace("-","").toUpperCase();
>                 //String url = "{\"uuid\":\""+uuid+"\",\"major\":\""+major+"\",\"minor\":\""+minor+"\"}";//String
> url =
> "{\"uuid\":\"EBEFD08370A247C89837E7B5634DF524\",\"major\":\"1\",\"minor\":\"1\"}";
>                 postService.Post(null,"Beacon_getUrl",null,this,uuid,major,minor);
>     
>                 //coment this to stop calling the Activity associated to the beacon detected
>                 //to work only once and stop searching if its still in the beaconRegion since it fired once already
>                 try {
>                     beaconManager.stopRangingBeaconsInRegion(region);
>                 }catch(RemoteException e){
>     
>                 }
>     
>             }
>         }
>     
>     
>     
>         //afther collecting information with the database that is the url associated to this ids
>         /*
>         Intent intent = new Intent(this, MainActivity.class);
>         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
>         this.startActivity(intent);
>         */
>     
>     }

您必须在 service

中包含您的后台逻辑

异步任务用于活动中的后台任务,to prevent UI freeze. In your case, you should use a Service to search for beacons. One of your activities will start the service when needed, then, when your service find your beacon, it will launch your Activity (maybe it's the time to stop the service). For more information about Services and best practices, don't forget the official documentation available here。 我希望我帮助了你。如果您需要进一步的帮助,请随时评论我的回复:)