package uk.co.alt236.btlescan.ui.main;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import com.anthonycr.grant.PermissionsManager;
import com.anthonycr.grant.PermissionsResultAction;
import java.util.ArrayList;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconType;
import uk.co.alt236.bluetoothlelib.device.beacon.BeaconUtils;
import uk.co.alt236.bluetoothlelib.device.beacon.ibeacon.IBeaconDevice;
import uk.co.alt236.btlescan.R;
import uk.co.alt236.btlescan.containers.BluetoothLeDeviceStore;
import uk.co.alt236.btlescan.ui.common.Navigation;
import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewBinderCore;
import uk.co.alt236.btlescan.ui.common.recyclerview.RecyclerViewItem;
import uk.co.alt236.btlescan.ui.main.recyclerview.model.IBeaconItem;
import uk.co.alt236.btlescan.ui.main.recyclerview.model.LeDeviceItem;
import uk.co.alt236.btlescan.util.BluetoothLeScanner;
import uk.co.alt236.btlescan.util.BluetoothUtils;
public class MainActivity extends AppCompatActivity {
@Bind(R.id.tvBluetoothLe)
protected TextView mTvBluetoothLeStatus;
@Bind(R.id.tvBluetoothStatus)
protected TextView mTvBluetoothStatus;
@Bind(R.id.tvItemCount)
protected TextView mTvItemCount;
@Bind(android.R.id.list)
protected RecyclerView mList;
@Bind(android.R.id.empty)
protected View mEmpty;
private RecyclerViewBinderCore mCore;
private BluetoothUtils mBluetoothUtils;
private BluetoothLeScanner mScanner;
private BluetoothLeDeviceStore mDeviceStore;
private DeviceRecyclerAdapter mRecyclerAdapter;
private final BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
final BluetoothLeDevice deviceLe = new BluetoothLeDevice(device, rssi, scanRecord, System.currentTimeMillis());
mDeviceStore.addDevice(deviceLe);
final List<RecyclerViewItem> itemList = new ArrayList<>();
for (final BluetoothLeDevice leDevice : mDeviceStore.getDeviceList()) {
if (BeaconUtils.getBeaconType(leDevice) == BeaconType.IBEACON) {
itemList.add(new IBeaconItem(new IBeaconDevice(leDevice)));
} else {
itemList.add(new LeDeviceItem(leDevice));
}
}
runOnUiThread(new Runnable() {
@Override
public void run() {
mRecyclerAdapter.setData(itemList);
updateItemCount(mRecyclerAdapter.getItemCount());
}
});
}
};
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mCore = RecyclerViewCoreFactory.create(this, new Navigation(this));
mList.setLayoutManager(new LinearLayoutManager(this));
mDeviceStore = new BluetoothLeDeviceStore();
mBluetoothUtils = new BluetoothUtils(this);
mScanner = new BluetoothLeScanner(mLeScanCallback, mBluetoothUtils);
updateItemCount(0);
}
@Override
public boolean onCreateOptionsMenu(final Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (!mScanner.isScanning()) {
menu.findItem(R.id.menu_stop).setVisible(false);
menu.findItem(R.id.menu_scan).setVisible(true);
menu.findItem(R.id.menu_refresh).setActionView(null);
} else {
menu.findItem(R.id.menu_stop).setVisible(true);
menu.findItem(R.id.menu_scan).setVisible(false);
menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_progress_indeterminate);
}
if (mRecyclerAdapter != null && mRecyclerAdapter.getItemCount() > 0) {
menu.findItem(R.id.menu_share).setVisible(true);
} else {
menu.findItem(R.id.menu_share).setVisible(false);
}
return true;
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_scan:
startScanPrepare();
break;
case R.id.menu_stop:
mScanner.scanLeDevice(-1, false);
invalidateOptionsMenu();
break;
case R.id.menu_about:
DialogFactory.createAboutDialog(this).show();
break;
case R.id.menu_share:
new Sharer().shareDataAsEmail(this, mDeviceStore);
}
return true;
}
@Override
protected void onPause() {
super.onPause();
mScanner.scanLeDevice(-1, false);
}
@Override
public void onResume() {
super.onResume();
if (mBluetoothUtils.isBluetoothOn()) {
mTvBluetoothStatus.setText(R.string.on);
} else {
mTvBluetoothStatus.setText(R.string.off);
}
if (mBluetoothUtils.isBluetoothLeSupported()) {
mTvBluetoothLeStatus.setText(R.string.supported);
} else {
mTvBluetoothLeStatus.setText(R.string.not_supported);
}
invalidateOptionsMenu();
}
private void startScanPrepare() {
//
// The COARSE_LOCATION permission is only needed after API 23 to do a BTLE scan
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PermissionsManager.getInstance().requestPermissionsIfNecessaryForResult(this,
new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, new PermissionsResultAction() {
@Override
public void onGranted() {
startScan();
}
@Override
public void onDenied(String permission) {
Toast.makeText(MainActivity.this,
R.string.permission_not_granted_coarse_location,
Toast.LENGTH_SHORT)
.show();
}
});
} else {
startScan();
}
}
private void startScan() {
final boolean isBluetoothOn = mBluetoothUtils.isBluetoothOn();
final boolean isBluetoothLePresent = mBluetoothUtils.isBluetoothLeSupported();
mDeviceStore.clear();
updateItemCount(0);
mRecyclerAdapter = new DeviceRecyclerAdapter(mCore);
mList.setAdapter(mRecyclerAdapter);
mBluetoothUtils.askUserToEnableBluetoothIfNeeded();
if (isBluetoothOn && isBluetoothLePresent) {
mScanner.scanLeDevice(-1, true);
invalidateOptionsMenu();
}
}
private void updateItemCount(final int count) {
mTvItemCount.setText(
getString(
R.string.formatter_item_count,
String.valueOf(count)));
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
PermissionsManager.getInstance().notifyPermissionsChange(permissions, grantResults);
}
}