/*
DeviceSelectionPageFragment.java
Copyright (c) 2014 NTT DOCOMO,INC.
Released under the MIT license
http://opensource.org/licenses/mit-license.php
*/
package org.deviceconnect.android.deviceplugin.sphero.setting.fragment;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;
import org.deviceconnect.android.deviceplugin.sphero.R;
import org.deviceconnect.android.deviceplugin.sphero.data.SpheroParcelable;
import org.deviceconnect.android.deviceplugin.sphero.setting.SettingActivity;
import org.deviceconnect.android.deviceplugin.sphero.setting.SettingActivity.DeviceControlListener;
import org.deviceconnect.android.deviceplugin.sphero.setting.widget.DeviceListAdapter;
import org.deviceconnect.android.deviceplugin.sphero.setting.widget.DeviceListAdapter.OnConnectButtonClickListener;
import org.deviceconnect.android.deviceplugin.sphero.util.BleUtils;
import java.util.List;
/**
* デバイス一覧画面.
* @author NTT DOCOMO, INC.
*/
public class DeviceSelectionPageFragment extends Fragment implements DeviceControlListener,
OnConnectButtonClickListener {
/**
* プログレス領域の可視フラグ.
*/
private static final String KEY_PROGRESS_VISIBILITY = "visible";
/**
* アダプター.
*/
private DeviceListAdapter mAdapter;
/**
* インジケーター.
*/
private ProgressDialog mIndView;
/**
* 検索ダイアログの表示状態.
*/
private int mSearchingVisibility = -1;
/**
* スレッドが定期的に動いているか.
*/
private boolean mIsThreadRunning = false;
/**
* Thread Handler.
*/
private final Handler mThreadHandler = new Handler();
private final Handler mReceiverHandler = new Handler();
private TextView mEmptyView;
private ListView mListView;
private View mProgressZone;
/**
* BluetoothのON/OFF時の挙動.
*/
private final BroadcastReceiver mSensorReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
if (state == BluetoothAdapter.STATE_ON ){
addFooterView();
if (BleUtils.isBLEPermission(getActivity())) {
startDiscoveryTimer();
}
} else if (state == BluetoothAdapter.STATE_OFF) {
addFooterView();
mIsThreadRunning = false;
stopDiscovery();
}
}
}
};
@Override
public void onAttach(final Activity activity) {
super.onAttach(activity);
((SettingActivity) activity).setDeviceControlListener(this);
mAdapter = new DeviceListAdapter(getActivity());
mAdapter.setOnConnectButtonClickListener(this);
((SettingActivity) activity).sendGetFoundedDevicesBroadcast();
}
@SuppressLint("InflateParams")
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
final Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.setting_device_list, null);
mEmptyView = (TextView) root.findViewById(R.id.device_list_empty);
mListView = (ListView) root.findViewById(R.id.device_list_view);
mListView.setAdapter(mAdapter);
mListView.setItemsCanFocus(true);
mProgressZone = root.findViewById(R.id.progress_zone);
return root;
}
@Override
public void onResume() {
super.onResume();
registerBluetoothFilter();
startDiscoveryTimer();
addFooterView();
}
@Override
public void onConnectedDevices(final List<Parcelable> devices) {
if (devices.size() == 0) {
startDiscoveryTimer();
} else {
for (Parcelable device : devices) {
if (device instanceof SpheroParcelable) {
for (int i = 0; i < mAdapter.getCount(); i++) {
SpheroParcelable s = mAdapter.getItem(i);
if (!s.getSpheroId().equals(((SpheroParcelable) device).getSpheroId())) {
mAdapter.add((SpheroParcelable) device);
} else {
mAdapter.changeConnectionState((SpheroParcelable) device);
}
}
}
}
}
}
@Override
public void onDeviceFound(final SpheroParcelable device) {
View root = getView();
if (root != null) {
View progressZone = root.findViewById(R.id.progress_zone);
progressZone.setVisibility(View.GONE);
}
boolean isExist = false;
for (int i = 0; i < mAdapter.getCount(); i++) {
SpheroParcelable s = mAdapter.getItem(i);
if (s.getSpheroId().equals(device.getSpheroId())) {
isExist = true;
}
}
if (!isExist) {
mAdapter.add(device);
} else {
mAdapter.changeConnectionState(device);
}
startDiscoveryTimer();
}
@Override
public void onDeviceLost(final SpheroParcelable device) {
//削除できる状態にする
mAdapter.changeConnectionState(device);
startDiscoveryTimer();
if (mIndView != null && mIndView.isShowing()) {
mIndView.dismiss();
}
}
@Override
public void onDeviceLostAll() {
mAdapter.clear();
View root = getView();
if (root != null) {
View progressZone = root.findViewById(R.id.progress_zone);
progressZone.setVisibility(View.VISIBLE);
}
}
@Override
public void onDeviceConnected(final SpheroParcelable device) {
if (mIndView != null) {
mIndView.dismiss();
}
if (device == null) {
AlertDialog.Builder builder = new Builder(getActivity());
builder.setTitle(R.string.title_error);
builder.setMessage(R.string.message_conn_error);
builder.setPositiveButton(R.string.btn_close, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
return;
}
mAdapter.changeConnectionState(device);
startDiscoveryTimer();
}
@Override
public void onDeviceDisconnected(SpheroParcelable device) {
if (device == null) {
AlertDialog.Builder builder = new Builder(getActivity());
builder.setTitle(R.string.title_error);
builder.setMessage(R.string.message_disconn_error);
builder.setPositiveButton(R.string.btn_close, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
return;
}
mAdapter.changeConnectionState(device);
startDiscoveryTimer();
}
@Override
public void onDeviceDeleted(SpheroParcelable device) {
if (device == null) {
AlertDialog.Builder builder = new Builder(getActivity());
builder.setTitle(R.string.title_error);
builder.setMessage(R.string.message_disconn_error);
builder.setPositiveButton(R.string.btn_close, new OnClickListener() {
@Override
public void onClick(final DialogInterface dialog, final int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
return;
}
mAdapter.remove(device);
startDiscoveryTimer();
}
@Override
public void onDestroyView() {
super.onDestroyView();
View root = getView();
if (root != null) {
View progressZone = root.findViewById(R.id.progress_zone);
mSearchingVisibility = progressZone.getVisibility();
}
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterBluetoothFilter();
mIsThreadRunning = false;
stopDiscovery();
}
@Override
public void onClicked(final int position, final SpheroParcelable device) {
Activity activity = getActivity();
if (activity == null) {
return;
}
mIsThreadRunning = false;
stopDiscovery();
if (device.isConnected() == SpheroParcelable.SpheroState.Connected) {
((SettingActivity) activity).sendDisonnectBroadcast(device.getSpheroId());
if (mAdapter.getCount() == 0) {
// 現在検知している場合は一旦検知をやめ、新たに検知を開始する.
startDiscoveryTimer();
}
} else if (device.isConnected() == SpheroParcelable.SpheroState.Remember
|| device.isConnected() == SpheroParcelable.SpheroState.Disconnected) {
mIndView = new ProgressDialog(activity);
mIndView.setMessage(activity.getString(R.string.connecting));
mIndView.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mIndView.setCancelable(false);
mIndView.show();
((SettingActivity) activity).sendConnectBroadcast(device.getSpheroId());
} else if (device.isConnected() == SpheroParcelable.SpheroState.Delete){
((SettingActivity) activity).sendDeleteSpheroBroadcast(device.getSpheroId());
}
}
/**
* 検知開始.
*/
private void startDiscovery() {
Activity activity = getActivity();
if (activity != null) {
((SettingActivity) activity).sendStartDiscoveryBroadcast();
View root = getView();
if (root != null) {
View progressZone = root.findViewById(R.id.progress_zone);
progressZone.setVisibility(View.VISIBLE);
}
}
}
/**
* 検知終了.
*/
private void stopDiscovery() {
Activity activity = getActivity();
if (activity != null) {
((SettingActivity) activity).sendStopDiscoveryBroadcast();
}
}
private void startDiscoveryTimer() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !BleUtils.isBLEPermission(getActivity())) {
return;
}
if (mIsThreadRunning) {
return;
}
mIsThreadRunning = true;
new Thread(new Runnable() {
@Override
public void run() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
return;
}
while (mIsThreadRunning) {
if (BluetoothAdapter.STATE_ON == mBluetoothAdapter.getState()) {
mThreadHandler.post(new Runnable() {
@Override
public void run() {
stopDiscovery();
startDiscovery();
}
});
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void registerBluetoothFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
getActivity().registerReceiver(mSensorReceiver, filter, null, mReceiverHandler);
}
private void unregisterBluetoothFilter() {
getActivity().unregisterReceiver(mSensorReceiver);
}
private void addFooterView() {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
if (!BleUtils.isBLEPermission(getActivity())) {
mEmptyView.setText(R.string.sphero_setting_dialog_error_permission);
mListView.setEmptyView(mEmptyView);
mProgressZone.setVisibility(View.GONE);
} else if (!BleUtils.isEnabled(getActivity())) {
mProgressZone.setVisibility(View.GONE);
mEmptyView.setText(R.string.sphero_setting_dialog_disable_bluetooth);
mListView.setEmptyView(mEmptyView);
} else if (BleUtils.isEnabled(getActivity())) {
mEmptyView.setText(R.string.no_devices);
mListView.setEmptyView(mEmptyView);
mProgressZone.setVisibility(View.VISIBLE);
}
}
});
}
}