2016-01-25 7 views
0

Я хочу автоматически запускать свою деятельность, когда маячок находится в пределах 1 метра. Этот вопрос был posed before, но я не могу заставить мой работать, используя/изменяя его код.Автозапуск на Eddystone-UID в пределах 1 метра

Как и этот пост, я выполнил те же шаги с помощью библиотеки маяков android через altbeacon github, но все еще не увенчался успехом.

У меня также есть "compile" org.altbeacon: android-beacon-library: 2.7+ '"в файле build.gradle.

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 
+0

Можете ли вы уточнить, почему вы оказались безуспешными? Код находится внутри блока 'if (beacons.size()> 0)'? Он попадает в блок 'if (beacon.getDistance() <1)'? – davidgyoung

+0

Это все; Я не знаю, почему его безуспешно. У меня есть маяк (Eddy-UID), подключенный и транслируемый (подтвержденный RadBeacon). Однако, когда мое устройство с установленным приложением (которое было открыто и запущено хотя бы один раз) получает менее 1 метра от маяка, оно не открывает приложение (либо на переднем плане, либо на фоне). Является ли мой код неправильным? Как я могу проверить, что вы предложили? –

ответ

0

Несколько советов:

  1. Попробуйте добавить строку отладки Log.d("Distance:"+beacon.get Distance());, прежде чем вы установите флажок для расстояния < 1. Затем запустите приложение, наблюдая за выходом LogCat, который ищет эту строку журнала.

  2. Поймите, что если у вас есть Android 4.x, это может занять до пяти минут, чтобы обнаружить в фоновом режиме.

  3. Всегда проще сначала получать приложения, работающие на переднем плане, а затем добавлять возможности фона. Убедитесь, что вы можете написать код, чтобы определить ваш маяк на переднем плане.

+0

Спасибо за помощь, Im работает под управлением Android 6 на Nexus 9. В сети радиуса другие приложения могут видеть маяк менее чем за 5 секунд. Я запустил logcat и получил огромный файл. Ive приложил выход в OP, так как у меня не хватает места в этой коробке. –

+0

Я также посмотрел дальше в файле logcat и обнаружил, что он нашел маяк и начал синтаксический анализ, но затем выдает предупреждение о ModelSpecificDistanceCalculator. Я читал в другом месте в Интернете, что это проблема синтаксического анализа, но разве мой код не обрабатывает маяк? –

+0

После выполнения большего исследования я считаю, что это ошибка, вызванная Android6. Marshmellow требует разрешения «ACCESS_COURSE_LOCATION» или «ACCESS_FINE_LOCATION» и приглашение пользователю разрешить это разрешение. Я добавил код разрешения Runtime: http://developer.radiusnetworks.com/2015/09/29/is-your-beacon-app-ready-for-android-6.html @ davidgyoung Вы можете посмотреть на мой пересмотренный MyApplication.java выше? Я импортировал каждый класс, но requestPermission и PERMISSION_REQUEST_COARSE_LOCATION не разрешают импортировать класс. Любая идея почему? –

0

С помощью кода davidgyoung размещенного на github, я был в состоянии решить эту проблему.