2016-09-18 22 views
0

まずは、数週間しかAndroidを学習していないことを指摘したいと思います。私は近くのブルートゥースの低エネルギーデバイスを(今のところログに)リストし、最終的にそれらに接続するアプリを作ろうとしています。Android 6.0でのBluetoothの位置情報の許可

このプロジェクトを開始して数週間後、ブルートゥースのスキャンに成功するために必要なAndroid 6.0の場所の権限でレンガの壁に当たった。次のコードは、私が現時点で持っているものです。

package com.benstechtips.bluetoothletest4; 

import android.annotation.TargetApi; 
import android.app.Activity; 
import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothGatt; 
import android.bluetooth.BluetoothGattCallback; 
import android.bluetooth.BluetoothGattCharacteristic; 
import android.bluetooth.BluetoothGattService; 
import android.bluetooth.BluetoothManager; 
import android.bluetooth.BluetoothProfile; 
import android.bluetooth.le.BluetoothLeScanner; 
import android.bluetooth.le.ScanCallback; 
import android.bluetooth.le.ScanFilter; 
import android.bluetooth.le.ScanResult; 
import android.bluetooth.le.ScanSettings; 
import android.content.Context; 
import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.os.Build; 
import android.os.Bundle; 
import android.os.Handler; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 
import android.widget.Toast; 

import java.util.ArrayList; 
import java.util.List; 

@TargetApi(21) 
public class MainActivity extends AppCompatActivity { 

private BluetoothAdapter mBluetoothAdapter; 
private int REQUEST_ENABLE_BT = 1; 
private Handler mHandler; 
private static final long SCAN_PERIOD = 10000; 
private BluetoothLeScanner mLEScanner; 
private ScanSettings settings; 
private List<ScanFilter> filters; 
private BluetoothGatt mGatt; 

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

    mHandler = new Handler(); 
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { 
     Toast.makeText(this, "BLE Not Supported", Toast.LENGTH_SHORT).show(); 
     finish(); 
    } 
    final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); 
    mBluetoothAdapter = bluetoothManager.getAdapter(); 


} 

@Override 
protected void onResume() { 
    super.onResume(); 

    if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { 
     Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 
    } else { 
     if (Build.VERSION.SDK_INT >= 21) { 
      mLEScanner = mBluetoothAdapter.getBluetoothLeScanner(); 
      settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 
      filters = new ArrayList<ScanFilter>(); 
     } 
     scanLeDevice(true); 
    } 
} 

@Override 
protected void onPause() { 
    super.onPause(); 
    if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) { 
     scanLeDevice(false); 
    } 
} 

@Override 
protected void onDestroy() { 
    if (mGatt == null) { 
     return; 
    } 
    mGatt.close(); 
    mGatt = null; 
    super.onDestroy(); 
} 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (requestCode == REQUEST_ENABLE_BT) { 
     if (resultCode == Activity.RESULT_CANCELED) { 
      //Bluetooth not enabled. 
      finish(); 
      return; 
     } 
    } 
    super.onActivityResult(requestCode, resultCode, data); 
} 

private void scanLeDevice(final boolean enable) { 
    if (enable) { 
     mHandler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
       Log.i("Scan Status", "Stopping Scan..."); 
       if (Build.VERSION.SDK_INT < 21) { 
        mBluetoothAdapter.stopLeScan(mLeScanCallback); 
       } else { 
        mLEScanner.stopScan(mScanCallback); 

       } 
      } 
     }, SCAN_PERIOD); 
     if (Build.VERSION.SDK_INT < 21) { 
      Log.i("Scan Status", "Starting Scan..."); 
      mBluetoothAdapter.startLeScan(mLeScanCallback); 
     } else { 
      mLEScanner.startScan(filters, settings, mScanCallback); 
     } 
    } else { 
     Log.i("Scan Status", "Stopping Scan..."); 
     if (Build.VERSION.SDK_INT < 21) { 
      mBluetoothAdapter.stopLeScan(mLeScanCallback); 
     } else { 
      mLEScanner.stopScan(mScanCallback); 
     } 
    } 
} 

private ScanCallback mScanCallback = new ScanCallback() { 
    @Override 
    public void onScanResult(int callbackType, ScanResult result) { 
     Log.i("callbackType", String.valueOf(callbackType)); 
     Log.i("result", result.toString()); 
     BluetoothDevice btDevice = result.getDevice(); 
     //connectToDevice(btDevice); 
    } 

    @Override 
    public void onBatchScanResults(List<ScanResult> results) { 
     for (ScanResult sr : results) { 
      Log.i("ScanResult - Results", sr.toString()); 
     } 
    } 

    @Override 
    public void onScanFailed(int errorCode) { 
     Log.e("Scan Failed", "Error Code: " + errorCode); 
    } 
}; 

private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { 
      @Override 
      public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Log.i("onLeScan", device.toString()); 
         //connectToDevice(device); 
        } 
       }); 
      } 
}; 

public void connectToDevice(BluetoothDevice device) { 
    if (mGatt == null) { 
     mGatt = device.connectGatt(this, false, gattCallback); 
     scanLeDevice(false);// will stop after first device detection 
    } 
} 

private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { 
    @Override 
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { 
     Log.i("onConnectionStateChange", "Status: " + status); 
     switch (newState) { 
      case BluetoothProfile.STATE_CONNECTED: 
       Log.i("gattCallback", "STATE_CONNECTED"); 
       gatt.discoverServices(); 
       break; 
      case BluetoothProfile.STATE_DISCONNECTED: 
       Log.e("gattCallback", "STATE_DISCONNECTED"); 
       break; 
      default: 
       Log.e("gattCallback", "STATE_OTHER"); 
     } 

    } 

    @Override 
    public void onServicesDiscovered(BluetoothGatt gatt, int status) { 
     List<BluetoothGattService> services = gatt.getServices(); 
     Log.i("onServicesDiscovered", services.toString()); 
     gatt.readCharacteristic(services.get(1).getCharacteristics().get 
       (0)); 
    } 

    @Override 
    public void onCharacteristicRead(BluetoothGatt gatt, 
            BluetoothGattCharacteristic 
              characteristic, int status) { 
     Log.i("onCharacteristicRead", characteristic.toString()); 
     gatt.disconnect(); 
    } 
}; 

さて、私の知る限り、以前のバージョン6.0へのAndroidのバージョンに、このコードは動作し、検出されたデバイスの名前を表示していました(Iデバイスにすぐに接続する機能が無効になっています)。しかし、Androidの6.0に、私は次のエラーを取得する:

java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results 

私はこれが私のアプリが必要な場所の権限を持っていないが原因であることを理解しています。私はAndroidManifest.xmlファイルに次のようなことがありますが、私はユーザーから許可を求める必要があることを知っています。

<?xml version="1.0" encoding="utf-8"?> 

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.BLUETOOTH"/> 
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/> 

<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/> 

<application 
    android:allowBackup="true" 
    android:icon="@mipmap/ic_launcher" 
    android:label="@string/app_name" 
    android:supportsRtl="true" 
    android:theme="@style/AppTheme"> 
    <activity android:name=".MainActivity"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN" /> 

      <category android:name="android.intent.category.LAUNCHER" /> 
     </intent-filter> 
    </activity> 
</application> 

しかし、私の質問は、私は、ユーザーの許可を要求しないか、でしょうか?

答えて

1

この同じ問題が発生しました。これは最近、マシュマロのセキュリティ機能として追加されました。私はちょうど粗い場所を選んだ

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 
     if (this.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
      requestPermissions(new String[]{android.Manifest.permission.ACCESS_COARSE_LOCATION}, 
        PERMISSION_REQUEST_COARSE_LOCATION); 
     } 
} 

private static final int PERMISSION_REQUEST_COARSE_LOCATION = 1; 

こと:ここで許可を要求すると、次のようになります。私が知る限り、どちらを選ぶかは問題ではありません。あなたはあなたの主な活動のためにこれをonCreateに入れることができます。お役に立てれば!

関連する問題