Eddystone-UID在1米范围内自动启动

时间:2016-01-25 03:34:14

标签: java android ibeacon-android altbeacon eddystone

当信标在1米范围内时,我想自动启动我的活动。这个问题已经posed before,但是我无法让我的工作使用/修改他的代码。

就像那篇文章一样,我通过altbeacon github跟踪了与android beacon库相同的步骤,但仍然没有成功。

我还在build.gradle文件中“编译'org.altbeacon:android-beacon-library:2.7+'”。

的AndroidManifest.xml:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.communionchapelefca.ccsatx" android:versionCode="1" android:versionName="1.0">
    <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    "android.hardware.bluetooth_le" android:required="false"/>
    <uses-permission-sdk-23 android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <application 
android:allowBackup="true" 
android:icon="@mipmap/ic_launcher" 
android:label="@string/app_name" 
android:theme="@style/AppTheme">
    <activity 
android:name="org.communionchapelefca.ccsatx.SplashScreen" android:label="@string/app_name" 
android:launchMode="singleInstance">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
    </activity>
    <activity 
android:name="org.communionchapelefca.ccsatx.MainActivity" android:label="@string/app_name" 
android:launchMode="singleInstance">
    <intent-filter>
    <action android:name="org.communionchapelefca.ccsatx.MAINACTIVITY"/>
    <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
    </activity>
    </application>
    </manifest>

MainActivity.java

import android.Manifest;
        import android.app.Activity;
        import android.app.AlertDialog;
        import android.app.Application;
        import android.content.DialogInterface;
        import android.content.Intent;
        import android.content.pm.PackageManager;
        import android.graphics.Bitmap;
        import android.os.Build;
        import android.os.Bundle;
        import android.os.RemoteException;
        import android.util.Log;
        import android.view.KeyEvent;
        import android.view.Menu;
        import android.view.MenuItem;
        import android.webkit.WebSettings;
        import android.webkit.WebView;
        import android.webkit.WebViewClient;
        import android.widget.ProgressBar;

        import org.altbeacon.beacon.Beacon;
        import org.altbeacon.beacon.BeaconManager;
        import org.altbeacon.beacon.BeaconParser;
        import org.altbeacon.beacon.RangeNotifier;
        import org.altbeacon.beacon.Region;
        import org.altbeacon.beacon.powersave.BackgroundPowerSaver;
        import org.altbeacon.beacon.startup.BootstrapNotifier;
        import org.altbeacon.beacon.startup.RegionBootstrap;

        import java.util.Collection;


public class MainActivity extends Activity implements BootstrapNotifier, RangeNotifier {
    public static final String TAG = "MainActivityCCSATX";
    private WebView mWebView;
    ProgressBar progressBar;
        private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1;


            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);

                setContentView(R.layout.activity_main);

                mWebView = (WebView) findViewById(R.id.activity_main_webview);

                progressBar = (ProgressBar) findViewById(R.id.progressBar1);

                WebSettings webSettings = mWebView.getSettings();
                webSettings.setJavaScriptEnabled(true);
                mWebView.loadUrl("http://communionchapelefca.org/edy-home");
                mWebView.setWebViewClient(new HelloWebViewClient());

                // begin code for bluetooth permission for android 6
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    // Android M Permission check

                    if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                        builder.setTitle("This app needs location access to find Communion Chapel beacons");
                        builder.setMessage("Please grant location access so this app can detect Communion Chapel beacons.");
                        builder.setPositiveButton(android.R.string.ok, null);
                        builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
                            @Override
                            public void onDismiss(DialogInterface dialog) {
                                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
                            }
                        });
                        builder.show();
                    }
                }

                mAllBeaconsRegion = new Region("all beacons", null, null, null);
                mBeaconManager = BeaconManager.getInstanceForApplication(this);
                mBackgroundPowerSaver = new BackgroundPowerSaver(this);
                mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);

                // 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
                //
                Log.d(TAG, " region.  starting ranging");

                mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
                mBeaconManager.setBackgroundScanPeriod(11000l);

            }

            @Override
            public void onRequestPermissionsResult(int requestCode,
                                                   String permissions[], int[] grantResults) {
                switch (requestCode) {
                    case PERMISSION_REQUEST_COARSE_LOCATION: {
                        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                            Log.d(TAG, "coarse location permission granted");
                        } else {
                            final AlertDialog.Builder builder = new AlertDialog.Builder(this);
                            builder.setTitle("Functionality limited");
                            builder.setMessage("Since location access has not been granted, this app will not be able to discover beacons when in the background.");
                            builder.setPositiveButton(android.R.string.ok, null);
                            builder.setOnDismissListener(new DialogInterface.OnDismissListener() {

                                @Override
                                public void onDismiss(DialogInterface dialog) {
                                }

                            });
                            builder.show();
                        }
                        return;
                    }
                }
            }

        // end code for bluetooth permission for android 6



    private class HelloWebViewClient extends WebViewClient{


        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            // TODO Auto-generated method stub
            super.onPageStarted(view, url, favicon);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url)
        {
            webView.loadUrl(url);
            return true;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            // TODO Auto-generated method stub
            super.onPageFinished(view, url);

            progressBar.setVisibility(view.GONE);
        }

    }


    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    { //if back key is pressed
        if((keyCode == KeyEvent.KEYCODE_BACK)&& mWebView.canGoBack())
        {
            mWebView.goBack();
            return true;

        }

        return super.onKeyDown(keyCode, event);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void onBackPressed() {
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                MainActivity.this);

        // set title
        alertDialogBuilder.setTitle("Exit");

        // set dialog message
        alertDialogBuilder
                .setMessage("Do you really want to exit?")
                .setCancelable(false)
                .setPositiveButton("Yes",new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        // if this button is clicked, close
                        // current activity
                        MainActivity.this.finish();
                    }
                })
                .setNegativeButton("No",new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int id) {
                        // if this button is clicked, just close
                        // the dialog box and do nothing
                        dialog.cancel();
                    }
                });

        // create alert dialog
        AlertDialog alertDialog = alertDialogBuilder.create();

        // show it
        alertDialog.show();
    }


    private RegionBootstrap regionBootstrap;
    private BeaconManager mBeaconManager;
    private Region region;
    private Region mAllBeaconsRegion;
    private BackgroundPowerSaver mBackgroundPowerSaver;
    private RegionBootstrap mRegionBootstrap;

    @Override
    public void didDetermineStateForRegion(int arg0, Region arg1) {
        // Don't care
    }

    @Override
    public void didEnterRegion(Region arg0) {

        mRegionBootstrap.disable();
        // 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.
        try {

            mBeaconManager.startRangingBeaconsInRegion(new Region("all beacons", null, null, null));
            mBeaconManager.setRangeNotifier(this);
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        Log.d(TAG, "Got a didEnterRegion call");

    }

    @Override
    public void didExitRegion(Region arg0) {
        // Don't care
    }

    @Override
    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
        // TODO Auto-generated method stub
        if (beacons.size() > 0) {

            for (Beacon beacon: beacons) {
                Log.d(TAG, "Found a beacon, getting distance");
                if(beacon.getDistance()<1)
                {
                    Log.d(TAG, "within 1 minute call");
                    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.
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    this.startActivity(intent);
                }

            }

        }
    }
}

LogCat致命错误:

01-28 17:23:38.819  6549  6724 D MainActivityCCSATX: Got a didEnterRegion call
01-28 17:23:38.824  6549  6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824  6549  6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:38.824  6549  6549 D BluetoothAdapter: STATE_ON
01-28 17:23:38.824  6549  6549 D BluetoothLeScanner: could not find callback wrapper
01-28 17:23:39.444  6549  6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549
01-28 17:23:40.023  6549  6549 W cr_BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 6549

2 个答案:

答案 0 :(得分:0)

一些提示:

  1. 在检查距离&lt;之前,请尝试添加调试行Log.d("Distance:"+beacon.get Distance());。 1.然后在观察LogCat输出时运行应用程序,查找该日志行。

  2. 了解如果您使用Android 4.x,则可能需要最多五分钟才能在后台进行检测。

  3. 首先让应用程序在前台工作更容易,然后添加后台功能。确保您可以编写代码以检测前景中的信标。

答案 1 :(得分:0)

github发布的davidgyoung代码的帮助下,我能够解决问题。