Commit 79136c8b by onuma

#47941 HW連携 @FormからBluetoothのソースを移植

parent bb6c99f5
......@@ -1514,4 +1514,7 @@
<string name="msg_agree_to_terms_of_use">利用規約に同意する</string>
<string name="clickable_detail_button">(詳細)</string>
<string name="err_gert_term_of_use_text">利用規約の取得に失敗しました。ネットワークの接続状態を確認してください。</string>
<!-- アルコールチェッカー -->
<string name="alc_setting">アルコールチェッカーHW設定</string>
<string name="bluetooth_is_not_supported">Bluetooth機能が利用できない端末です。</string>
</resources>
......@@ -1519,4 +1519,7 @@
<string name="msg_agree_to_terms_of_use">이용약관에 동의함</string>
<string name="clickable_detail_button">(상세)</string>
<string name="err_gert_term_of_use_text">이용약관을 얻지 못했습니다. 네트워크 연결 상태를 확인해주세요.</string>
<!-- アルコールチェッカー -->
<string name="alc_setting">알코올 검사기 HW 설정</string>
<string name="bluetooth_is_not_supported">블루투스는 지원되지 않습니다.</string>
</resources>
\ No newline at end of file
......@@ -1515,4 +1515,7 @@
<string name="msg_agree_to_terms_of_use">I agree to the terms of use</string>
<string name="clickable_detail_button">(detail)</string>
<string name="err_gert_term_of_use_text">Failed to get the terms of use. Check the network connection status.</string>
<!-- アルコールチェッカー -->
<string name="alc_setting">alc checker setting</string>
<string name="bluetooth_is_not_supported">Bluetooth is not supported.</string>
</resources>
......@@ -73,4 +73,11 @@
android:layout="@layout/custom_preference_screen">
</PreferenceScreen>
</PreferenceCategory>
<PreferenceCategory android:title="@string/alc_setting" android:key="@string/alc_setting" android:layout="@layout/custom_preference_category">
<PreferenceScreen
android:key="pairingBluetooth"
android:title="@string/alc_setting"
android:layout="@layout/custom_preference_screen">
</PreferenceScreen>
</PreferenceCategory>
</PreferenceScreen>
\ No newline at end of file
package jp.agentec.abook.abv.cl.util;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import java.util.UUID;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.adf.util.StringUtil;
import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
import static org.chromium.base.ThreadUtils.runOnUiThread;
public class BleManagerUtil {
private final String TAG = "BleManagerUtil";
private BluetoothManager bluetoothManager;
private Context mContext;
private BleManagerUtilListener mListener;
private Handler mHandler;
// 定数(Bluetooth LE Gatt UUID)
// Private Service
private UUID UUID_SERVICE_PRIVATE;
private UUID UUID_CHARACTERISTIC_PRIVATE;
// for Notification
private UUID UUID_NOTIFY;
// メンバー変数
public BluetoothAdapter mBluetoothAdapter; // BluetoothAdapter : Bluetooth処理で必要
private String mDeviceAddress = ""; // デバイスアドレス
public BluetoothGatt mBluetoothGatt = null; // Gattサービスの検索、キャラスタリスティックの読み書き
private int mBleConnectDeviceType;
public BleManagerUtil(Context context, BleManagerUtilListener listener) {
mContext = context;
mListener = listener;
mHandler = new Handler();
}
// BluetoothGattコールバック
private final BluetoothGattCallback mGattcallback = new BluetoothGattCallback() {
// 接続状態変更(connectGatt()の結果として呼ばれる。)
@Override
public void onConnectionStateChange(BluetoothGatt gatt, final int status, final int newState ) {
Logger.d("onConnectionStateChange status = " + status + " newState = " + newState);
// デバイスと接続されていない場合のメッセージコード:133, 62
// デバイスと離れて応答がなく、タイムアウトになる場合:8
// デバイスと接続が切れた場合のメッセージコード:19
if (status == 133 || status == 62 || status == 8 || status == 19) { // 接続失敗
runOnUiThread( new Runnable() {
@Override
public void run() {
mListener.onConnectionError(status);
}
});
return;
}
if( status == BluetoothGatt.GATT_SUCCESS && BluetoothProfile.STATE_CONNECTED == newState ) {
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
@Override
public void run() {
// 接続完了
if (mBluetoothGatt == null || !mBluetoothGatt.discoverServices()) { // サービス検索
runOnUiThread( new Runnable() { // 接続失敗
@Override
public void run() {
mListener.onGetDeviceInfoFailed(status);
Logger.e("onConnectionStateChange2 status = " + status);
}
});
}
}
}, 600);
return;
}
if( BluetoothProfile.STATE_DISCONNECTED == newState ) { // 切断完了(接続可能範囲から外れて切断された)
// 切断が発生する場合、Bluetoothと接続を切断する。
disconnect(true);
return;
}
}
// サービス検索が完了したときの処理(mBluetoothGatt.discoverServices()の結果として呼ばれる。)
@Override
public void onServicesDiscovered( BluetoothGatt gatt, int status ) {
if( BluetoothGatt.GATT_SUCCESS != status ) {
return;
}
Logger.d(TAG, "--gattSize : " + gatt.getServices().size());
if (gatt.getServices().size() == 0) {
// サービスがない場合は、再接続
bleGattReconnect();
return;
}
mBluetoothGatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
// 発見されたサービスのループ
for(BluetoothGattService service : gatt.getServices()) {
// サービスごとに個別の処理
if((service == null) || (service.getUuid() == null)) {
continue;
}
// GATTサービスのキャラクタリスティックを列挙
List<BluetoothGattCharacteristic> listCharacteristic = service.getCharacteristics();
for (BluetoothGattCharacteristic characteristic : listCharacteristic) {
// 利用したいものがあるはず!
Logger.d(TAG, "characteristic : [ " + characteristic );
}
// プライベートサービス
if(UUID_SERVICE_PRIVATE.equals(service.getUuid())) {
// 最初の読み取り
readCharacteristic(UUID_SERVICE_PRIVATE, UUID_CHARACTERISTIC_PRIVATE);
runOnUiThread( new Runnable() {
@Override
public void run() {
// 操作可能
mListener.onConnectionState();
}
});
continue;
}
}
}
// キャラクタリスティックが読み込まれたときの処理
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status ) {
if( BluetoothGatt.GATT_SUCCESS != status ) {
return;
}
if( UUID_CHARACTERISTIC_PRIVATE.equals(characteristic.getUuid())) {
// final String strTemperature = byteToString(characteristic.getValue());
// runOnUiThread( new Runnable() {
// @Override
// public void run() {
// // 芯温計の温度を渡す。
// // 端末と接続時に呼ばれるのでコメント処理
//// mListener.onGetDeviceInfo(strTemperature);
// }
// });
// 通知設定
setCharacteristicNotification(UUID_SERVICE_PRIVATE, UUID_CHARACTERISTIC_PRIVATE, true);
return;
}
}
// キャラクタリスティック変更が通知されたときの処理
@Override
public void onCharacteristicChanged( BluetoothGatt gatt, BluetoothGattCharacteristic characteristic ) {
if( UUID_CHARACTERISTIC_PRIVATE.equals( characteristic.getUuid() ) ) {
final String strTemperature = byteToString(characteristic.getValue());
runOnUiThread( new Runnable() {
@Override
public void run() {
// 複数呼ばれるため、mBluetoothGattがnullの場合、以下の処理を行わない
if(mBluetoothGatt == null) {
return;
}
// 芯温計の温度を渡す。
mListener.onGetDeviceInfo(strTemperature);
}
});
return;
}
}
};
/**
* 接続してるデバイスタイプを取得
* @return
*/
public int getBluetoothDeviceType() {
return mBleConnectDeviceType;
}
// スキャンコールバック
private final ScanCallback mScanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, final ScanResult result) {
super.onScanResult(callbackType, result);
runOnUiThread(new Runnable() {
@Override
public void run() {
BluetoothDevice device = result.getDevice();
Logger.d(TAG, "--scaning : " + device.getName() );
if (device.getAddress().equals(mDeviceAddress)) {
// 異常と見做し、stopScanでエラーを返す。
stopScan(device.getAddress());
}
}
});
}
// スキャンに失敗
@Override
public void onScanFailed(final int errorCode) {
super.onScanFailed(errorCode);
Logger.e(TAG, "scan failed errorCode : " + errorCode);
runOnUiThread( new Runnable() {
@Override
public void run() {
mListener.onConnectionError(errorCode);
}
});
}
};
/**
* スキャンを中止
*/
private void stopScan(String deviceAddress) {
Logger.d(TAG, "stop ble scan");
// 一定期間後にスキャン停止するためのHandlerのRunnableの削除
mHandler.removeCallbacksAndMessages(null);
if (StringUtil.isNullOrEmpty(deviceAddress)) {
// deviceAddressが見つからなかったと見做し、エラーで返す。
mListener.onConnectionError(-1);
return;
}
// スキャン停止
mBluetoothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
// ble接続
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
bleGattConnect(device);
}
/**
* ディバイス情報の取得を開始します<br>
* 成功時にlistenerのonGetDeviceInfo、失敗時にlistenerのonGetDeviceInfoFailedが呼び出されます。
*
*/
public interface BleManagerUtilListener {
void onGetDeviceInfo(String strTemperature); // ディバイスから渡す情報
void onGetDeviceInfoFailed(int status); // ディバイスと接続失敗時の情報渡す。
void onConnectionState(); // ディバイスと接続された時情報渡す。
void onDisConnectionState(); // ディバイスと切断時
void onConnectionError(int status); // ディバイス接続エラー
}
// 接続
public void connect(int connectTargetDeviceType, String deviceAddress) {
mDeviceAddress = deviceAddress;
// デバイスタイプセット
mBleConnectDeviceType = connectTargetDeviceType;
setUUID();
if(StringUtil.isNullOrEmpty(mDeviceAddress)) { // DeviceAddressが空の場合は処理しない
return;
}
if(mBluetoothGatt != null) { // mBluetoothGattがnullでないなら接続済みか、接続中。
return;
}
// mBluetoothGattのサービスと接続
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceAddress);
if (device.getName() == null) {
// deviceの名称がない場合、接続エラーになるため、再スキャンすることで検知したらgetRemoteDeviceメソッドに名称がセットされる
mBluetoothAdapter.getBluetoothLeScanner().startScan(mScanCallback);
// スキャン開始(一定時間後にスキャン停止する)
mHandler.postDelayed( new Runnable() {
@Override
public void run() {
// 20秒後に呼ばれた時はスキャンで端末を取得できなかったと見做す。
stopScan(null);
Logger.d(TAG, "scan in 20 sec");
}
}, 20000 );
} else {
bleGattConnect(device);
}
}
/**
* GATT BLE接続処理
* @param device
*/
private void bleGattConnect(BluetoothDevice device) {
// GATT BLEを利用する時Androidのバージョン「23」をチェックしてGATTと接続する。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mBluetoothGatt = device.connectGatt(mContext, false, mGattcallback, TRANSPORT_LE);
} else {
mBluetoothGatt = device.connectGatt(mContext, false, mGattcallback );
}
// 該当デバイスのキャッシュをリフレッシュ
refreshDeviceCache(mBluetoothGatt);
}
// 切断
public void disconnect(boolean listenerFlg) {
if(mBluetoothGatt == null) {
return;
}
// 切断
// mBluetoothGatt.disconnect()ではなく、mBluetoothGatt.close()しオブジェクトを解放する。
// 理由:「ユーザーの意思による切断」と「接続範囲から外れた切断」を区別するため。
// ①「ユーザーの意思による切断」は、mBluetoothGattオブジェクトを解放する。再接続は、オブジェクト構築から。
// ②「接続可能範囲から外れた切断」は、内部処理でmBluetoothGatt.disconnect()処理が実施される。
// 切断時のコールバックでmBluetoothGatt.connect()を呼んでおくと、接続可能範囲に入ったら自動接続する。
mBluetoothGatt.disconnect();
// mBluetoothGatt.close();
mBluetoothGatt = null;
if (listenerFlg) {
runOnUiThread( new Runnable() {
@Override
public void run() {
// 切断トーストメッセージを表示する。
mListener.onDisConnectionState();
}
});
}
}
// キャラクタリスティックの読み込み
private void readCharacteristic( UUID uuid_service, UUID uuid_characteristic ) {
if( null == mBluetoothGatt ) {
return;
}
BluetoothGattCharacteristic blechar = mBluetoothGatt.getService( uuid_service ).getCharacteristic( uuid_characteristic );
mBluetoothGatt.readCharacteristic( blechar );
}
// キャラクタリスティック通知の設定
private void setCharacteristicNotification( UUID uuid_service, UUID uuid_characteristic, boolean enable ) {
if( null == mBluetoothGatt ) {
return;
}
BluetoothGattService service = mBluetoothGatt.getService( uuid_service );
if(service == null) {
return;
}
BluetoothGattCharacteristic blechar = service.getCharacteristic( uuid_characteristic );
mBluetoothGatt.setCharacteristicNotification( blechar, enable );
BluetoothGattDescriptor descriptor = blechar.getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
descriptor.setValue( BluetoothGattDescriptor.ENABLE_INDICATION_VALUE );
mBluetoothGatt.writeDescriptor(descriptor);
}
// Signed short (16-bit) Two's complement to short, String
public String byteToString(byte[] bytes) {
short sht = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN).getShort();
float flt = sht / (float)100;
return String.valueOf(flt);
}
// Bluetoothアダプタの取得処理
public void startDeviceInfo() {
// Bluetoothアダプタの取得
BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService( Context.BLUETOOTH_SERVICE );
if (bluetoothManager != null) {
mBluetoothAdapter = bluetoothManager.getAdapter();
if( mBluetoothAdapter == null ) { // Android端末がBluetoothをサポートしていない
Toast.makeText( mContext, R.string.bluetooth_is_not_supported, Toast.LENGTH_SHORT ).show();
return;
}
} else {
Logger.e(TAG, "bluetoothManager is null");
}
}
// UUIDセット
private void setUUID() {
// if (mBleConnectDeviceType == DeviceType.centerThermomete) {
// // 中心温度計のUUIDセット
// UUID_SERVICE_PRIVATE = UUID.fromString("05fd8c58-9d23-11e7-abc4-cec278b6b50a");
// UUID_CHARACTERISTIC_PRIVATE = UUID.fromString("05fd8f5a-9d23-11e7-abc4-cec278b6b50a");
// } else if (mBleConnectDeviceType == DeviceType.radiationThermomete) {
// // 放射温度計のUUIDセット
// UUID_SERVICE_PRIVATE = UUID.fromString("462026f6-cfe1-11e7-abc4-cec278b6b50a");
// UUID_CHARACTERISTIC_PRIVATE = UUID.fromString("46202b74-cfe1-11e7-abc4-cec278b6b50a");
// }
}
/**
* bleGattのcache更新
* @param gatt
* @return
*/
private boolean refreshDeviceCache(BluetoothGatt gatt){
try {
BluetoothGatt localBluetoothGatt = gatt;
Method localMethod = localBluetoothGatt.getClass().getMethod("refresh", new Class[0]);
if (localMethod != null) {
boolean bool = ((Boolean) localMethod.invoke(localBluetoothGatt, new Object[0])).booleanValue();
return bool;
}
}
catch (Exception localException) {
Logger.e(TAG, "An exception occured while refreshing device");
}
return false;
}
/**
* 再接続処理
*/
private void bleGattReconnect() {
disconnect(false);
connect(mBleConnectDeviceType, mDeviceAddress);
}
}
......@@ -87,6 +87,9 @@ public class ABookSettingFragment extends PreferenceFragment {
private static final String ABOOK_CHECK_MANUAL = "abookCheckManual";
private static final String PRIVACY_POLICY = "privacyPolicy";
// ペアリング情報
private static final String PAIRING_BLUETOOTH = "pairingBluetooth";
protected Handler handler = new Handler();
protected AlertDialog alertDialog = null;
private SharedPreferences pref;
......@@ -240,6 +243,15 @@ public class ABookSettingFragment extends PreferenceFragment {
return true;
}
});
// // ペアリング情報
// Preference pairingBluetooth = findPreference(PAIRING_BLUETOOTH);
// pairingBluetooth.setOnPreferenceClickListener(new OnPreferenceClickListener() {
// @Override
// public boolean onPreferenceClick(Preference preference) {
// return false;
// }
// });
// ライセンス情報
Preference licenseInfo = findPreference(LICENSE_INFO);
......@@ -285,28 +297,10 @@ public class ABookSettingFragment extends PreferenceFragment {
appInfo.removePreference(checkAppUpdate);
}
// 不要?
Preference abookCheckManual = findPreference(ABOOK_CHECK_MANUAL);
appInfo.removePreference(abookCheckManual);
// // リソースパターンの適用
// abookCheckManual.setTitle(PatternStringUtil.patternToString(getActivity().getApplicationContext(),
// R.string.operation_manual,
// getUserPref(getActivity().getApplicationContext(), AppDefType.UserPrefKey.RESOURCE_PATTERN_TYPE, 0)));
// abookCheckManual.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
// @Override
// public boolean onPreferenceClick(Preference preference) {
// try {
// Intent intent = new Intent();
// intent.putExtra(ABookKeys.CONTENT_ID, 0L);
// intent.putExtra("FILEPATH", ABVEnvironment.getInstance().getContentCacheDirectoryPath(0L));
// intent.putExtra("page", 0);
// intent.setClass(getActivity(), GuideViewActivity.class);
// startActivity(intent);
// } catch (Exception e) {
// Logger.e(TAG, e);
// }
// return true;
// }
// });
}
private void showLicenseDialog() {
......
package jp.agentec.abook.abv.ui.home.activity;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import jp.agentec.abook.abv.bl.common.Constant;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.abook.abv.cl.util.BleManagerUtil;
import jp.agentec.abook.abv.launcher.android.R;
import jp.agentec.abook.abv.ui.common.activity.ABVUIActivity;
import jp.agentec.abook.abv.ui.common.util.ABVToastUtil;
import jp.agentec.abook.abv.ui.home.helper.ABookPermissionHelper;
import jp.agentec.adf.util.CollectionUtil;
public class BlePairingSettingActivity extends ABVUIActivity {
private static final String TAG = "BlePairingSettingActivity";
// 定数
private static final int REQUEST_ENABLEBLUETOOTH = 1; // Bluetooth機能の有効化要求時の識別コード
private static final long SCAN_PERIOD = 20000; // スキャン時間。単位はミリ秒。
private static final String CENTER_THERMOMETE_DEVICE_NAME = "MF500"; // 中心温度計のデバイス名
private static final String RADIATION_THERMOMETE_DEVICE_NAME = "IR-TB"; // 放射温度計のデバイス名
// メンバー変数
private Handler mHandler; // UIスレッド操作ハンドラ : 「一定時間後にスキャンをやめる処理」で必要
private boolean mScanning = false; // スキャン中かどうかのフラグ
private Button mButton_Scan;
private BleManagerUtil bleManagerUtil;
private BleListAdapter mBleListAdapter; // Adapter
private List<BluetoothDevice> mScanDeviceInfoList = new ArrayList<BluetoothDevice>();
private List<String> mSavedDeviceAddressList = new ArrayList<String>(); //登録した端末アドレス
// デバイススキャンコールバック
private ScanCallback mLeScanCallback = new ScanCallback() {
// スキャンに成功(アドバタイジングは一定間隔で常に発行されているため、本関数は一定間隔で呼ばれ続ける)
@Override
public void onScanResult( int callbackType, final ScanResult result ) {
super.onScanResult( callbackType, result );
runOnUiThread( new Runnable() {
@Override
public void run() {
BluetoothDevice device = result.getDevice();
if (device.getName() != null) {
Logger.d("mScanCallback device.getName() = " + device.getName());
}
// 識別商品名に絞る
if(device.getName() != null && (device.getName().startsWith(CENTER_THERMOMETE_DEVICE_NAME) || device.getName().startsWith(RADIATION_THERMOMETE_DEVICE_NAME))) {
if (!mSavedDeviceAddressList.contains(device.getAddress())) { //登録されたデバイスの場合、スキャン情報から除外する。
boolean isAdd = true;
for (BluetoothDevice savedDevice : mScanDeviceInfoList) {
if (savedDevice.getAddress().equals(device.getAddress())) {
// スキャンされたデバイス情報リストから一つでも一致する場合、既にスキャンされたと見做し追加しない。
isAdd = false;
}
}
if (isAdd) {
mScanDeviceInfoList.add(device);
}
reloadListView();
}
Logger.d("device.getName() = " + device.getName() + "device.getAddress() = " + device.getAddress() );
}
}
} );
}
// スキャンに失敗
@Override
public void onScanFailed( int errorCode ) {
super.onScanFailed( errorCode );
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
Logger.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
setContentView(R.layout.pairing_setting);
TextView deviceTitle = (TextView) findViewById(R.id.device_toolbar_title);
deviceTitle.setText(getString(R.string.chino_machine));
// 戻り値の初期化
setResult( Activity.RESULT_CANCELED );
List<SectionHeaderData> sectionList = getSectionListInfo();
List<List<BleListRowData>> rowList = getRowListInfo();
mBleListAdapter = new BleListAdapter( this, sectionList, rowList, new BleListAdapter.BleListAdapterListener() { // ビューアダプターの初期化
@Override
public void onDeleteConnectInfo(BleListRowData rowData) { // 登録されたデバイス情報削除
Logger.i(rowData.deviceAddress);
Integer deviceType = null;
if (rowData.title.startsWith(CENTER_THERMOMETE_DEVICE_NAME)) {
deviceType = DeviceType.centerThermomete;
} else if (rowData.title.startsWith(RADIATION_THERMOMETE_DEVICE_NAME)) {
deviceType = DeviceType.radiationThermomete;
}
if (deviceType != null) {
// 機器連携の情報をローカルに削除する。
getABVUIDataCache().removePairingBluetoothDeviceInfo(deviceType);
}
// 保存済みのアドレスを管理するメンバー変数も削除
mSavedDeviceAddressList.remove(rowData.deviceAddress);
reloadListView();
//スキャン実行中ではない場合はスキャン実行
if (!mScanning) {
startScan();
}
}
});
// Bluetoothと接続処理する
bleManagerUtil = new BleManagerUtil(this, null);
bleManagerUtil.startDeviceInfo();
// bleManagerUtil.mBluetoothAdapter.startDiscovery();
ListView listView = (ListView) findViewById(R.id.devicelist); // リストビューの取得
listView.setAdapter(mBleListAdapter); // リストビューにビューアダプターをセット
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Logger.d(TAG, "position = " + position);
BleListRowData bleListRowData = (BleListRowData)parent.getItemAtPosition(position);
// 既に保存されてる場合は何もしない
if (!bleListRowData.isSaved) {
localSaveDeviceInfo(bleListRowData);
}
}
});
// Reload Button
mButton_Scan = (Button)findViewById( R.id.btn_reload );
mButton_Scan.setAllCaps(false);
mButton_Scan.setText(getString(R.string.pairing_search_scan));
mButton_Scan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mScanning) {
stopScan();
} else {
startScan();
}
}
});
// UIスレッド操作ハンドラの作成(「一定時間後にスキャンをやめる処理」で使用する)
mHandler = new Handler();
}
// 初回表示時、および、ポーズからの復帰時
@Override
protected void onResume() {
super.onResume();
//画面表示時にスキャン実行
startScan();
}
// 別のアクティビティ(か別のアプリ)に移行したことで、バックグラウンドに追いやられた時
@Override
protected void onPause() {
super.onPause();
// スキャンの停止
stopScan();
}
// 機能の有効化ダイアログの操作結果
// 機能の有効化ダイアログの操作結果
@Override
protected void onActivityResult( int requestCode, int resultCode, Intent data ) {
switch (requestCode) {
case REQUEST_ENABLEBLUETOOTH: // Bluetooth有効化要求
if( Activity.RESULT_CANCELED == resultCode ) { // 有効にされなかった
ABVToastUtil.showMakeText(getApplicationContext(), String.format(getString(R.string.msg_scan_bluetooth_no_allow), getString(R.string.chino_machine)), Toast.LENGTH_SHORT);
return;
}
break;
}
super.onActivityResult( requestCode, resultCode, data );
}
// スキャンの開始
private void startScan() {
//BlueTooth許可チェック
if (!requestBluetoothFeature()) return;
LocationManager lm = (LocationManager) this.getSystemService(this.LOCATION_SERVICE);
boolean gpsEnabled = false;
if (lm != null) {
gpsEnabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
} else {
Logger.w(TAG, "LocationManager is null");
}
// GPSの状態を取得(getSystemtServiceからのGPS ON/OFF取得が取れない場合があるため、secureで取得したgpsも判定するため)
final boolean secureLocationGpsEnabled = android.provider.Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED).contains("gps");
//端末側の位置情報許可チェック
if (!(gpsEnabled || secureLocationGpsEnabled)) {
showSimpleAlertDialog(R.string.chino_machine, R.string.msg_location_device_no_allow);
return;
}
ABookPermissionHelper helper = new ABookPermissionHelper(this, Constant.ABookPermissionType.AccessFineLocation, null);
//アプリ側の位置情報許可チェック(置くだけセンサーとLinkingアプリの通信できないため)
if (!helper.checkMultiPermissions(true)) return;
// BluetoothLeScannerの取得
// ※Runnableオブジェクト内でも使用できるようfinalオブジェクトとする。
BluetoothLeScanner scanner = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
scanner = bleManagerUtil.mBluetoothAdapter.getBluetoothLeScanner();
}
if (scanner == null) {
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scanner.startScan(mLeScanCallback);
}
// スキャン開始(一定時間後にスキャン停止する)
mHandler.postDelayed( new Runnable() {
@Override
public void run() {
stopScan();
Logger.d(TAG, "scan in 20 sec");
}
}, SCAN_PERIOD );
mScanning = true;
mButton_Scan.setText(getString(R.string.pairing_search_stop));
reloadListView();
Logger.d(TAG, "start scan !!");
}
// スキャンの停止
private void stopScan() {
// 一定期間後にスキャン停止するためのHandlerのRunnableの削除
mHandler.removeCallbacksAndMessages( null );
// BluetoothLeScannerの取得
BluetoothLeScanner scanner = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
scanner = bleManagerUtil.mBluetoothAdapter.getBluetoothLeScanner();
}
if(scanner == null) {
return;
}
mScanning = false;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
scanner.stopScan( mLeScanCallback );
}
mButton_Scan.setText(getString(R.string.pairing_search_scan));
reloadListView();
Logger.d(TAG, "stop scan !!");
}
private void localSaveDeviceInfo(BleListRowData bleListRowData) {
// アドレスが保存されてる場合無視
if (!mSavedDeviceAddressList.contains(bleListRowData.deviceAddress)) {
mSavedDeviceAddressList.add(bleListRowData.deviceAddress);
BluetoothPairingDeviceInfoDto pairingDeviceInfo = new BluetoothPairingDeviceInfoDto();
if (bleListRowData.title.startsWith(CENTER_THERMOMETE_DEVICE_NAME)) {
// デバイス名がMF500から始まると中心温度計と見做す。
pairingDeviceInfo.deviceType = DeviceType.centerThermomete;
} else if (bleListRowData.title.startsWith(RADIATION_THERMOMETE_DEVICE_NAME)) {
// デバイス名がIR-TBから始まると放射温度計と見做す。
pairingDeviceInfo.deviceType = DeviceType.radiationThermomete;
}
// 上記のdeviceTypeがセットされた場合のみ、ローカルのxmlに保存する
if (pairingDeviceInfo.deviceType != null) {
pairingDeviceInfo.deviceName = bleListRowData.title;
pairingDeviceInfo.deviceAddress = bleListRowData.deviceAddress;
// 機器連携の情報をローカルに保存する。
getABVUIDataCache().setPairingBluetoothDeviceInfo(pairingDeviceInfo);
}
// スキャンされた情報から保存されたのでdeviceは削除
for (BluetoothDevice savedScanDevice : mScanDeviceInfoList) {
if (savedScanDevice.getAddress().equals(bleListRowData.deviceAddress)) {
mScanDeviceInfoList.remove(savedScanDevice);
break;
}
}
//画面リロード
reloadListView();
}
}
// 閉じるボタンの処理
public void onClickCloseView(View v) {
finish();
}
/**
* ListViewのSectionデータを作成する。
* @return Rowデータリスト
*/
private List<SectionHeaderData> getSectionListInfo() {
List<SectionHeaderData> sectionList = new ArrayList<>();
List<BluetoothPairingDeviceInfoDto> bluetoothPairingInfoDtoList = getABVUIDataCache().getPairingBluetoothDeviceInfoList(Arrays.asList(DeviceType.centerThermomete, DeviceType.radiationThermomete));
if (CollectionUtil.isNotEmpty(bluetoothPairingInfoDtoList)) {
for (BluetoothPairingDeviceInfoDto bluetoothPairingDeviceInfoDto : bluetoothPairingInfoDtoList) {
// ペアリング情報が既に保存されてる場合はヘッダー情報を各機器毎に追加する
if (bluetoothPairingDeviceInfoDto.deviceType.equals(DeviceType.centerThermomete)) {
sectionList.add(new SectionHeaderData(String.format(getString(R.string.pairing_save_machine), getString(R.string.center_thermometer))));
} else if (bluetoothPairingDeviceInfoDto.deviceType.equals(DeviceType.radiationThermomete)) {
sectionList.add(new SectionHeaderData(String.format(getString(R.string.pairing_save_machine), getString(R.string.radiation_thermometer))));
}
}
}
// その他のヘッダー情報追加
sectionList.add(new SectionHeaderData(String.format(getString(mScanning ? R.string.pairing_other_machine_searching : R.string.pairing_other_machine), getString(R.string.chino_machine))));
return sectionList;
}
/**
* ListViewのRowデータを作成する。
* @return Rowデータリスト
*/
private List<List<BleListRowData>> getRowListInfo() {
List<List<BleListRowData>> rowList = new ArrayList<List<BleListRowData>>();
// 引数で指定したタイプリストのペアリング情報を取得
List<BluetoothPairingDeviceInfoDto> bluetoothPairingInfoDtoList = getABVUIDataCache().getPairingBluetoothDeviceInfoList(Arrays.asList(DeviceType.centerThermomete, DeviceType.radiationThermomete));
if (CollectionUtil.isNotEmpty(bluetoothPairingInfoDtoList)) {
for (BluetoothPairingDeviceInfoDto bluetoothPairingDeviceInfoDto : bluetoothPairingInfoDtoList) {
List<BleListRowData> rowDataList = new ArrayList<BleListRowData>();
BleListRowData rowData = new BleListRowData(bluetoothPairingDeviceInfoDto.deviceName, bluetoothPairingDeviceInfoDto.deviceAddress, true);
rowDataList.add(rowData);
rowList.add(rowDataList);
// 保存された情報であれば、メンバー変数で管理するため、listに追加、既に存在する場合は何もしない
if (!mSavedDeviceAddressList.contains(bluetoothPairingDeviceInfoDto.deviceAddress)) {
mSavedDeviceAddressList.add(bluetoothPairingDeviceInfoDto.deviceAddress);
}
}
}
if (mScanDeviceInfoList.size() == 0) {
List<BleListRowData> scanRowDataList = new ArrayList<BleListRowData>();
BleListRowData scanRowData = new BleListRowData("" , "" );
scanRowDataList.add(scanRowData);
rowList.add(scanRowDataList);
} else {
List<BleListRowData> scanRowDataList = new ArrayList<BleListRowData>();
for (BluetoothDevice bleDevice : mScanDeviceInfoList) {
String labelDeviceName = "";
if (bleDevice.getName().startsWith(CENTER_THERMOMETE_DEVICE_NAME)) {
labelDeviceName = getString(R.string.center_thermometer);
} else if (bleDevice.getName().startsWith(RADIATION_THERMOMETE_DEVICE_NAME)) {
labelDeviceName = getString(R.string.radiation_thermometer);
}
BleListRowData scanRowData = new BleListRowData(bleDevice.getName(), labelDeviceName, bleDevice.getAddress(), false);
scanRowDataList.add(scanRowData);
}
rowList.add(scanRowDataList);
}
return rowList;
}
/**
* ListViewをリロードする。
*/
private void reloadListView() {
List<SectionHeaderData> sectionList = getSectionListInfo();
List<List<BleListRowData>> rowList = getRowListInfo();
mBleListAdapter.setItem(sectionList, rowList);
}
// デバイスのBluetooth機能の有効化要求
private boolean requestBluetoothFeature() {
if(bleManagerUtil.mBluetoothAdapter.isEnabled()) {
return true;
}
// デバイスのBluetooth機能が有効になっていないときは、有効化要求(ダイアログ表示)
Intent enableBtIntent = new Intent( BluetoothAdapter.ACTION_REQUEST_ENABLE );
startActivityForResult( enableBtIntent, REQUEST_ENABLEBLUETOOTH );
return false;
}
}
package jp.agentec.abook.abv.ui.home.adapter;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.util.List;
import jp.agentec.abook.abv.launcher.android.R;
public class BleListAdapter {
public class BleListAdapter extends BaseSectionAdapter<SectionHeaderData, BleListRowData> {
private static final String TAG = "BleListAdapter";
protected jp.agentec.abook.abv.ui.home.adapter.BleListAdapter.BleListAdapterListener listener;
public interface BleListAdapterListener {
// 登録されたデバイス情報削除(bluetooth情報を引数としてセット)
void onDeleteConnectInfo(BleListRowData rowData);
}
public BleListAdapter(Context context, List<SectionHeaderData> sectionList,
List<List<BleListRowData>> rowList, BleListAdapterListener listener) {
super(context, sectionList, rowList);
this.listener = listener;
}
@Override
public View viewForHeaderInSection(View convertView, int section) {
ListHeaderViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.ble_section_list_header, null);
holder = new ListHeaderViewHolder();
holder.titleTxt = (TextView) convertView.findViewById(R.id.titleTxt);
holder.subtitleTxt = (TextView) convertView.findViewById(R.id.subTitleTxt);
convertView.setTag(holder);
} else {
holder = (ListHeaderViewHolder) convertView.getTag();
}
SectionHeaderData headerData = sectionList.get(section);
holder.titleTxt.setText(headerData.title);
holder.subtitleTxt.setText(headerData.subTitle);
return convertView;
}
@Override
public View cellForRowAtIndexPath(View convertView, IndexPath indexPath) {
ListRowViewHolder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.ble_section_list_row, null);
holder = new ListRowViewHolder();
// bluetoothのデバイス名
holder.bl_title = (TextView) convertView.findViewById(R.id.bl_title);
// 該当通信機器の名(中心温度計・放射温度計)
holder.sub_title = (TextView) convertView.findViewById(R.id.sub_title);
// 削除ボタン
holder.bl_deleteBtn = (Button) convertView.findViewById(R.id.bl_deleteBtn);
convertView.setTag(holder);
} else {
holder = (ListRowViewHolder) convertView.getTag();
}
final BleListRowData rowData = rowList.get(indexPath.section).get(indexPath.row);
holder.bl_title.setText(rowData.title);
if (rowData.isSaved) {
// 既に保存されてる場合、削除ボタン表示・機器名は非表示
holder.sub_title.setVisibility(View.GONE);
holder.bl_deleteBtn.setVisibility(View.VISIBLE);
holder.bl_deleteBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onDeleteConnectInfo(rowData);
}
});
} else {
// スキャンされたbluetooth機器表示時に削除ボタンと接続ステータス非表示
holder.bl_deleteBtn.setVisibility(View.GONE);
holder.sub_title.setVisibility(View.VISIBLE);
holder.sub_title.setText(rowData.subTitle);
}
return convertView;
}
static class ListHeaderViewHolder {
TextView titleTxt;
TextView subtitleTxt;
}
static class ListRowViewHolder {
TextView bl_title;
TextView sub_title;
Button bl_deleteBtn;
}
public void setItem(List<SectionHeaderData> sectionList, List<List<BleListRowData>> rowList) {
settingSectionRowData(sectionList, rowList);
notifyDataSetChanged();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment