從頭開始敲代碼之《從BaseApplication/Activity開始(二)》,applicationactivity
轉載請註明出處:王亟亟的大牛之路
願意花時間寫東西不容易,人啊,都是有血有肉有思想的,借鑒是學習,純Copy就不好了,謝謝
部分資料參考於網上。
《贈梁任父同年》黃遵憲
寸寸河山寸寸金,侉離分裂力誰任?
杜鵑再拜憂天淚,Data Replication System無窮填海心。
上一篇我們講到了簡易的封裝 對我們提高效率的好處,這一篇繼續寫下去,如果第一篇沒看過的希望能看下,方便理解。連結:亟亟在安卓的進階執行個體
這一次我們利用最基本的Activity生命週期中的方法,來對使用者藍芽進行識別操作,並在過程中考慮使用者層面的操作理解,順便補充下安卓手機的藍芽知識。
什麼是藍芽?
一種無線技術標準,可實現固定裝置、行動裝置和樓宇個人域網之間的短距離資料交換(使用2.4—2.485GHz的ISM波段的UHF無線電波)。
白話:安卓對各個版本的藍芽其實都有一定的支援,從1.5的Cupcake就支援了藍芽耳機,但是自從安卓4.3版本之後Google對藍芽4.0的支援,又進一步的提升,所以對4.3前後的適配又成了我們的工作(現在已經普遍以5.0為開發環境低版本的手機已經不多,工作量其實已經不大了)
OK,簡單介紹完了,開始今天的代碼
寫一個工具類BluetoothMgr,把藍芽一些相關的操作,放在裡面
/** * Created by Ezreal on 2015/9/14. */public class BluetoothMgr { private static BluetoothMgr oneInstance = null; public static BluetoothAdapter mBluetoothAdapter = null; public boolean available = false; private static List<BluetoothDevice> devList = new ArrayList<BluetoothDevice>(); private BluetoothMgr() { } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private BluetoothMgr(Context context) { int sdkInt = Build.VERSION.SDK_INT; if (sdkInt <= Build.VERSION_CODES.JELLY_BEAN_MR1) { mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); } else { BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = manager.getAdapter(); } available = (null != mBluetoothAdapter); } //判斷BluetoothMgr是否可用 public boolean available() { return available; } //獲得執行個體 public static BluetoothMgr getInstance(Context context) { if (null == oneInstance) { oneInstance = new BluetoothMgr(context); } return oneInstance; } //搜尋裝置 public static boolean startDiscovery(){ if (null == mBluetoothAdapter) { return false; } if (!mBluetoothAdapter.isEnabled()) { mBluetoothAdapter.enable(); while (!mBluetoothAdapter.isEnabled()) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } if (mBluetoothAdapter.isDiscovering()) { return true; } return mBluetoothAdapter.startDiscovery(); } //取消搜尋 public static boolean cancelDiscovery() { if (mBluetoothAdapter == null) { return false; } if (mBluetoothAdapter.isDiscovering()){ return mBluetoothAdapter.cancelDiscovery(); } return false; } //添加裝置 public static void addOne(BluetoothDevice device) { if (null == device) { return; } if (devList.contains(device)) { return; } devList.add(device); } //刪除裝置 public static void deleteOne(String mac) { if (null == mac || mac.length()==0) { return; } for (int i = 0; i < devList.size(); ++i) { BluetoothDevice device = devList.get(i); if (device.getAddress().equalsIgnoreCase(mac)) { devList.remove(i); break; } } } //清空集合 public static void clearAllDevices() { devList.clear(); } public static BluetoothDevice findOne(int pos) { if (pos < 0 || pos >= devList.size()) { return null; } return devList.get(pos); } public static List<BluetoothDevice> getDevList() { return devList; } public static boolean isDevListEmpty() { return (null == devList || devList.isEmpty()); } //擷取狀態 public static int getState(){ if(mBluetoothAdapter!=null){ LogUtils.d("BluetoothMgr","mBluetoothAdapter.getState()"+mBluetoothAdapter.getState()); return mBluetoothAdapter.getState(); }else{ return -1; } }}
分析:對藍芽的一些基本方法進行了封裝,以及版本的判斷,這邊在例舉下藍芽相關的一些具體代碼的內容
(這部分網上資料還算有,也可以找找)
在安卓要使用藍芽,先要授權
<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
不然你項目一運行就是異常。
要使用藍芽必須聲明一個BluetoothAdapter
在4.3之前
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();擷取系統預設藍芽。
4.3之後
BluetoothManager manager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
列舉一些常用的方法
disable()關閉藍芽
enable()開啟藍芽(使用者將不會收到提示)
下面是另一種開啟藍芽的方式,但是會提醒使用者手動去開啟
Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
cancelDiscovery() 取消搜尋裝置
startDiscovery() 開始搜尋裝置
getAddress()擷取本地藍芽地址
getName()擷取本地藍芽名稱
getRemoteDevice(Stringaddress)根據藍芽地址擷取遠程藍牙裝置
getState()擷取本地藍芽適配器目前狀態
isDiscovering()判斷當前是否正在尋找裝置,是返回true
isEnabled()判斷藍芽是否開啟,已開啟返回true,否則,返回false
再列舉下藍芽的狀態值
BluetoothAdapter STATE 狀態值
int STATE_OFF 藍芽已經關閉 int STATE_ON 藍芽已經開啟 int STATE_TURNING_OFF 藍芽處於關閉過程中 ,關閉ing int STATE_TURNING_ON 藍芽處於開啟過程中 ,開啟ing
BluetoothAdapter SCAN_MOD狀態值=掃描狀態
可以掃描其他裝置的,當然它同時能被其他藍牙裝置掃碼。
int SCAN_MODE_CONNECTABLE 表明該藍芽可以掃描其他藍牙裝置 int SCAN_MODE_CONNECTABLE_DISCOVERABLE 可以掃描其他藍牙裝置,並且可以被其他藍牙裝置掃描到。 int SCAN_MODE_NONE : 該藍芽不能掃描以及被掃描。
更多資料可參考BluetoothAdapter[藍芽]
鋪墊做的差不多了,我們開始今天的代碼。
需求:我有一個Activity,我需要進入他的時候讓使用者開啟手機藍芽,然後對我們的另外一個藍芽硬體進行操作,如果使用者不願意去開,那就停留在原有介面,如果使用者去開藍芽了並且成功了那麼就進入下一步操作,如果沒開成功,那麼繼續提示。
包結構:
代碼的基類都是在我們之前的Demo中繼續添加的,更有延續性。
直接貼 MainActivity
public class MainActivity extends BaseActivity implements View.OnClickListener{ Button button; private MyPromptDlg btNotOpenDlg = null; BluetoothMgr bleMgr; @Override protected void findById() { button=(Button)findViewById(R.id.button); bleMgr=BluetoothMgr.getInstance(this); } @Override protected void setListener() { button.setOnClickListener(this); } @Override protected void logic() { } @Override protected int getLayout() { return R.layout.activity_main; } @Override public void onClick(View v) { if (v.getId()==R.id.button){ Toast.makeText(MainActivity.this,"NFC是否可用?? "+NFCisAvailable(),Toast.LENGTH_SHORT).show(); openBlueToothSetting(); } } @Override protected void onResume() { super.onResume(); LogUtils.d("------>onResume"); if(bleMgr.isEnabled()){ Toast.makeText(MainActivity.this,"藍芽已經開啟",Toast.LENGTH_SHORT).show(); }else{ OpenBlueTooth(); } } //開啟藍芽 private void OpenBlueTooth(){ //判斷Activity的狀態 if (this.isFinishing()) { return; } if (null == btNotOpenDlg) { MyPromptDlg.Builder builder = new MyPromptDlg.Builder(this); builder.setTitle(res.getString(R.string.prompt_dlg_title)) .setText(res.getString(R.string.bt_check_message)) .setPositiveButton(res.getString(R.string.common_ok), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); openBlueToothSetting(); } }) .setNegativeButton(res.getString(R.string.common_cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); //finish(); } }); btNotOpenDlg = builder.create(); btNotOpenDlg.setCancelable(false); btNotOpenDlg.setCanceledOnTouchOutside(false); } if (!btNotOpenDlg.isShowing()) { btNotOpenDlg.show(); } } //開啟系統藍芽設定菜單 private void openBlueToothSetting(){ Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }}
分析:
首先我們在我們的onCreate方法中初始化一個BluetoothMgr並且讓其獲得了系統藍芽的執行個體(包中的BluetoothMgr是一個Demo版的,具體更多的通用方法封裝在JAR包中了)
使用者進入App 依次調用onCreate–onStart–onResume–Activity進入運行狀態。
我們在onCreate時並沒有對使用者的藍芽狀態進行判斷,而是在onResume方法中判斷,這是為什嗎?看
因為onResume會多次調用,而onCreate在不被回收過或者onStop的情況下永遠就調用一次,我們需要每一次使用者焦點在我們App中的時候都去判斷藍芽的狀態,那就是為什麼我們要這麼做的原因。
為了提高我們App的友好度,在判斷使用者沒有開啟藍芽的時候,我們彈出一個Dialog提示使用者要不要去開藍芽,
如果使用者點擊取消我們會回到介面,但是不會調用onResume方法,不然我們的使用者 就一直在那裡選啊選了,不符合邏輯。
點擊是,調用openBlueToothSetting()方法去手動開啟,當然如果你覺得你需要強勢一些可以用enable()方法,直接就開啟了,但是要記得做短暫的等待,因為開啟藍芽會有一定的非同步作業。
因為你代碼調用開啟藍芽所以使用者回到介面之後不會再判斷時候開啟藍芽,也符合我們的業務需求。
當使用者點擊確定的時候我們開啟了藍芽設定菜單介面(系統的)
回來之後又調用了onResume,彈出了我們的多士
OK我們的業務就完成了,還有別的實現方法嗎?有!!
可以用Service,開一個現成一直在那裡判斷也能達到效果 但是不是最理想的實現方式
還有是BroadcastReceiver 去監聽手機藍芽的變化,實現如下
BroadcastReceiver bluetoothState = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { String stateExtra = BluetoothAdapter.EXTRA_STATE; int state = intent.getIntExtra(stateExtra, -1); switch(state) { case BluetoothAdapter.STATE_TURNING_ON: break; case BluetoothAdapter.STATE_ON: break; case BluetoothAdapter.STATE_TURNING_OFF: break; case BluetoothAdapter.STATE_OFF: break; } }}registerReceiver(bluetoothState,new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
記得登出哦!!
午休午休!!源碼地址:http://yunpan.cn/cmCaaRkzc2UV6 訪問密碼 4894
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。