Android BLE4.0通訊之計步、體重、血壓
新手剛接觸藍芽4.0,好不容易實現了讀取藍芽上的步數,體重上的資料和血壓計的資料。網上資料真的很難找。
掃描藍芽裝置的Activity
public class DeviceScanActivity extends ListActivity { private final static int REQUEST_ENABLE_BT = 1; private boolean mScanning; private LeDeviceListAdapter mLeDeviceListAdapter; private Handler mHandler; privateBluetoothAdapter mBluetoothAdapter; private static final long SCAN_PERIOD = 10000; public static int MY_ACCESS_COARSE_LOCATION = 7895; boolean mHasPermission = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //getActionBar().setTitle(R.string.title_device);if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_support, Toast.LENGTH_SHORT).show(); finish(); } BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter= bluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Toast.makeText(this, R.string.error_bluetooth_not_support, Toast.LENGTH_SHORT).show(); finish(); return; } if(ContextCompat.checkSelfPermission(this,Manifest.permission.ACCESS_COARSE_LOCATION)!=PackageManager.PERMISSION_GRANTED){ mHasPermission = false; }else { mHasPermission = true; } if(!mHasPermission) { //申請ACCESS_COARSE_LOCATION許可權 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, MY_ACCESS_COARSE_LOCATION); Toast.makeText(this, "do not has ACCESS_COARSE_LOCATION Permission!!!", Toast.LENGTH_LONG).show(); } mHandler = new Handler(); scanLeDevice(true); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); doNext(requestCode, grantResults); } private void doNext(int requestCode, int[] grantResults) { if (requestCode == MY_ACCESS_COARSE_LOCATION) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // Permission Granted 允許授予的許可權 // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to // BluetoothAdapter through BluetoothManager. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); // Checks if Bluetooth is supported on the device. if (mBluetoothAdapter == null) { //Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); finish(); return; } //mHasPermission = true; } else { // Permission Denied Toast.makeText(this, "No Permission!!!", Toast.LENGTH_LONG).show(); //mHasPermission = false; finish(); } } } @Override protected void onResume() { super.onResume(); if (mHasPermission) { if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(mBluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } mLeDeviceListAdapter = new LeDeviceListAdapter(); setListAdapter(mLeDeviceListAdapter); scanLeDevice(true); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED){ finish(); return; } super.onActivityResult(requestCode, resultCode, data); } @Override protected void onPause() { super.onPause(); mLeDeviceListAdapter.clear(); scanLeDevice(false); } public void scanLeDevice(final boolean enable){ if(enable){ mHandler.postDelayed(new Runnable() { @Override public void run() { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); invalidateOptionsMenu(); } },SCAN_PERIOD); mScanning = true; mBluetoothAdapter.startLeScan(mLeScanCallback); }else { mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } invalidateOptionsMenu(); } 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() { mLeDeviceListAdapter.addDevice(device); mLeDeviceListAdapter.notifyDataSetChanged(); } }); } }; public class LeDeviceListAdapter extends BaseAdapter{ private ArrayList<BluetoothDevice> mLeDevices; private LayoutInflater mInflater; public LeDeviceListAdapter(){ super(); mLeDevices = new ArrayList<BluetoothDevice>(); mInflater = DeviceScanActivity.this.getLayoutInflater(); } public void addDevice(BluetoothDevice device){ if(!mLeDevices.contains(device)){ mLeDevices.add(device); } } public void clear(){ mLeDevices.clear(); } public BluetoothDevice getDevice(int position){ return mLeDevices.get(position); } @Override public int getCount() { return mLeDevices.size(); } @Override public Object getItem(int position) { return mLeDevices.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View view, ViewGroup parent) { ViewHolder viewHolder; if(view == null){ viewHolder = new ViewHolder(); view = mInflater.inflate(R.layout.listitem_device,null); viewHolder.deviceName = (TextView)view.findViewById(R.id.receiver_data_display); viewHolder.deviceAddress = (TextView)view.findViewById(R.id.device_address_display); view.setTag(viewHolder); }else { viewHolder = (ViewHolder)view.getTag(); } BluetoothDevice device = mLeDevices.get(position); final String deviceName = device.getName(); if(deviceName != null && deviceName.length()>0) viewHolder.deviceName.setText(deviceName); else viewHolder.deviceName.setText(R.string.unknow_device); viewHolder.deviceAddress.setText(device.getAddress()); return view; } } public class ViewHolder { TextView deviceName; TextView deviceAddress; } @Override protected void onListItemClick(ListView l, View v, int position, long id) { final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position); if(device == null) return; Intent intent = new Intent(this,DeviceControlActivity.class); intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_NAME,device.getName()); intent.putExtra(DeviceControlActivity.EXTRAS_DEVICE_ADDRESS,device.getAddress()); if(mScanning){ mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback); } startActivity(intent); } }
管理裝置和顯示資料的Activity
public class DeviceControlActivity extends Activity { public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME"; public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS"; private String mDeviceName; private String mDeviceAddress; private TextView mConnectionState; private TextView mBattery; private TextView mBleBattery; private TextView mManufacturer; private TextView mStepCount; private TextView mBodyWeight; private TextView mShrink; private TextView mDiastole; private TextView mHeartRate; private TextView mRange; //private ExpandableListView mGattServicesList; private BluetoothLeService mBluetoothLeService; private MyThread mt = null; private double weight; private boolean finish = true; private boolean mConnected = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.gatt_services_characteristics); Intent intent = getIntent(); mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME); mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS); mBattery = (TextView)findViewById(R.id.battery); mBleBattery = (TextView)findViewById(R.id.ble_battery); mManufacturer = (TextView)findViewById(R.id.manufacturer); mStepCount = (TextView)findViewById(R.id.step_count); mBodyWeight = (TextView)findViewById(R.id.body_weight); mShrink = (TextView)findViewById(R.id.shrink); mDiastole = (TextView)findViewById(R.id.diastole); mHeartRate = (TextView)findViewById(R.id.heart_rate); mRange = (TextView)findViewById(R.id.range); ((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress); mConnectionState = (TextView) findViewById(R.id.connection_state); getActionBar().setTitle(mDeviceName); getActionBar().setDisplayHomeAsUpEnabled(true); Intent gattServiceIntent = new Intent(this, BluetoothLeService.class); bindService(gattServiceIntent, conn, BIND_AUTO_CREATE); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 1: String battery = msg.getData().getString("battery"); if (battery != null) { Log.d("demo", String.valueOf(Integer.parseInt(battery, 16))); int level = Integer.parseInt(battery, 16); mBleBattery.setText(level + "%"); } break; case 2: String manufacturer = msg.getData().getString("manufacturer"); if (manufacturer != null) { mManufacturer.setText(manufacturer); } break; case 3: String data = msg.getData().getString("count"); String count = data.substring(4, 10); int stepCount = Integer.parseInt(count, 16); mStepCount.setText(stepCount + ""); break; case 4: String body_weight = msg.getData().getString("bodyweight"); String bw = body_weight.substring(4, 8); getWeight(bw); break; case 5: Bundle b = msg.getData(); mBodyWeight.setText(b.getDouble("weight")+" kg"); if (weight == 0.0) { mHandler.removeCallbacks(mt); mt = null; } break; case 6: String blood = msg.getData().getString("bloodpressure"); getBloodPressure(blood); break; default: break; } } }; public void getBloodPressure(String data){ String sk = data.substring(20,24); int shrink = Integer.parseInt(sk,16); mShrink.setText(shrink+" mmHg"); String dia = data.substring(24,26); int diastole = Integer.parseInt(dia,16); mDiastole.setText(diastole+" mmHg"); String hr = data.substring(26,28); int heart = Integer.parseInt(hr,16); mHeartRate.setText(heart+" BPM"); getRange(shrink,diastole); } public void getRange(int shrink,int diastole){ if((shrink>=90 && shrink<140) && (diastole>=60 && diastole<90)){ mRange.setText(R.string.normal); }else if(shrink>139 || diastole>90){ mRange.setText(R.string.high); }else if(shrink<90 || diastole<60){ mRange.setText(R.string.low); }else if(shrink>139 && diastole<90){ mRange.setText(R.string.isolated_systolic_hypertension); } } public void getWeight(String s){ int a = Integer.parseInt(s,16); if (mt == null) { mt = new MyThread(); mt.start(); } double w = a; weight = w/10; } @Override protected void onResume() { super.onResume(); registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); } @Override protected void onPause() { super.onPause(); unregisterReceiver(mGattUpdateReceiver); } @Override protected void onDestroy() { super.onDestroy(); unbindService(conn); mBluetoothLeService = null; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.gatt_service, menu); if (mConnected) { menu.findItem(R.id.menu_connect).setVisible(false); menu.findItem(R.id.menu_disconnect).setVisible(true); } else { menu.findItem(R.id.menu_connect).setVisible(true); menu.findItem(R.id.menu_disconnect).setVisible(false); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_connect: mBluetoothLeService.connect(mDeviceAddress); return true; case R.id.menu_disconnect: mBluetoothLeService.disconnect(); return true; } return super.onOptionsItemSelected(item); } private final ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mBluetoothLeService = ((BluetoothLeService.LocalBind) service).getService(); if (!mBluetoothLeService.initialize()) { finish(); } mBluetoothLeService.connect(mDeviceAddress); } @Override public void onServiceDisconnected(ComponentName name) { mBluetoothLeService = null; } }; private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); Bundle bundle = new Bundle(); Message msg = new Message(); Log.d("demo", action); if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) { mConnected = true; updateConnectionState(R.string.connected); invalidateOptionsMenu(); } else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) { mConnected = false; updateConnectionState(R.string.disconnected); invalidateOptionsMenu(); //clearUI(); } else if (BluetoothLeService.ACTION_GATT_SERVICES_DISCOVER.equals(action)) { mBluetoothLeService.readBattery(); } else if (BluetoothLeService.ACTION_DATA_BLOODPRESSURE.equals(action)) { //displayBloodPressure(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); bundle.putString("bloodpressure", intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); msg.setData(bundle); msg.what = 6; mHandler.sendMessage(msg); } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { int level = intent.getIntExtra("level", 0);//獲取當前電量 int scale = intent.getIntExtra("scale", 100);//電量的總刻度 mBattery.setText(((level * 100) / scale) + "%");//把它轉成百分比 } else if (BluetoothLeService.ACTION_DATA_BATTERY.equals(action)) { //displayBleBattery(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); bundle.putString("battery", intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); msg.setData(bundle); msg.what = 1; mHandler.sendMessage(msg); } else if (BluetoothLeService.ACTION_DATA_MENUFACTURER.equals(action)) { //displayManufacturer(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); bundle.putString("manufacturer", intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); msg.setData(bundle); msg.what = 2; mHandler.sendMessage(msg); } else if (BluetoothLeService.ACTION_DATA_COUNT.equals(action)) { //displayCount(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); bundle.putString("count", intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); msg.setData(bundle); msg.what = 3; mHandler.sendMessage(msg); } else if (BluetoothLeService.ACTION_DATA_BODYWEIGHT.equals(action)) { //displayBodyWeight(intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); bundle.putString("bodyweight", intent.getStringExtra(BluetoothLeService.EXTRA_DATA)); msg.setData(bundle); msg.what = 4; mHandler.sendMessage(msg); } } }; private void updateConnectionState(final int resourceId) { runOnUiThread(new Runnable() { @Override public void run() { mConnectionState.setText(resourceId); } }); } /*private void clearUI() { mGattServicesList.setAdapter((SimpleExpandableListAdapter) null); }*/ /* private void displayBloodPressure(String data) { if (data != null) { mBloodPressure.setText(data); } } private void displayBodyWeight(String data) { if (data != null) { mBodyWeight.setText(data); } }*/ /* public void displayBleBattery(String data){ Log.d("demo", "battery data != null --->"+String.valueOf(data!=null)); if(data != null){ Log.d("demo", String.valueOf(Integer.parseInt(data,16))); int level = Integer.parseInt(data, 16); mBleBattery.setText(level+"%"); } }*/ /* public void displayManufacturer(String data) { if (data != null) { mManufacturer.setText(data); } } public void displayCount(String data) { if (data != null) { String count = data.substring(4, 10); Log.d("demo", count); Log.d("demo", String.valueOf(Integer.parseInt(count, 16))); int stepCount = Integer.parseInt(count, 16); mStepCount.setText(stepCount + ""); } }*/ private static IntentFilter makeGattUpdateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothLeService.ACTION_GATT_CONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_DISCONNECTED); intentFilter.addAction(BluetoothLeService.ACTION_GATT_SERVICES_DISCOVER); intentFilter.addAction(BluetoothLeService.ACTION_DATA_BLOODPRESSURE); intentFilter.addAction(BluetoothLeService.ACTION_DATA_BODYWEIGHT); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); intentFilter.addAction(BluetoothLeService.ACTION_DATA_MENUFACTURER); intentFilter.addAction(BluetoothLeService.ACTION_DATA_BATTERY); intentFilter.addAction(BluetoothLeService.ACTION_DATA_COUNT); return intentFilter; } class MyThread extends Thread { @Override public void run() { super.run(); while (finish) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } Message msg = new Message(); Bundle bundle = new Bundle(); bundle.putDouble("weight", weight); msg.setData(bundle); msg.what = 5; mHandler.sendMessage(msg); } } } }
服務類
public class BluetoothLeService extends Service { private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; private int mConnectionState = STATE_DISCONNECTED; private Handler mHandler = new Handler(); private final static int STATE_DISCONNECTED = 0; private final static int STATE_CONNECTING = 1; private final static int STATE_CONNECTED = 2; private final static int RUN_PERIOD = 3000; private final static int COUNT_PERIOD = 3000; public final static String ACTION_GATT_CONNECTED = "com.example.chongyanghu.ble.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.chongyanghu.ble.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVER = "com.example.chongyanghu.ble.ACTION_GATT_SERVICES_DISCOVER"; public final static String EXTRA_DATA = "com.example.chongyanghu.ble.EXTRA_DATA"; public final static String ACTION_DATA_BATTERY = "com.example.chongyanghu.ble.ACTION_DATA_BATTERY"; public final static String ACTION_DATA_MENUFACTURER = "com.example.chongyanghu.ble.ACTION_DATA_MENUFACTURER"; public final static String ACTION_DATA_COUNT = "com.example.chongyanghu.ble.ACTION_DATA_COUNT"; public final static String ACTION_DATA_BLOODPRESSURE = "com.example.chongyanghu.ble.ACTION_DATA_BLOODPRESSURE"; public final static String ACTION_DATA_BODYWEIGHT = "com.example.chongyanghu.ble.ACTION_DATA_BODYWEIGHT"; //public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); public final static String BATTERY_SERVICE = "0000180F-0000-1000-8000-00805f9b34fb"; public final static String BATTERY_CHARATERISTIC = "00002a19-0000-1000-8000-00805f9b34fb"; public final static String MANUFACTURER_SERVICE = "0000180a-0000-1000-8000-00805f9b34fb"; public final static String MANUFACTURER_CHARATERISTIC = "00002a29-0000-1000-8000-00805f9b34fb"; public final static String CUSTOM_SERVICE = "0000ffe0-0000-1000-8000-00805f9b34fb"; public final static String CUSTOM_CHARACTERISTIC = "0000ffe1-0000-1000-8000-00805f9b34fb"; private final IBinder mBinder = new LocalBind(); @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } public class LocalBind extends Binder { BluetoothLeService getService() { return BluetoothLeService.this; } } @Override public boolean onUnbind(Intent intent) { close(); return super.onUnbind(intent); } public boolean initialize() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } return true; } public void disconnect() { if (mBluetoothAdapter == null ||相關推薦
Android BLE4.0通訊之計步、體重、血壓
新手剛接觸藍芽4.0,好不容易實現了讀取藍芽上的步數,體重上的資料和血壓計的資料。網上資料真的很難找。 掃描藍芽裝置的Activity public class DeviceScanActivity extends ListActivity { private
Android 8.0 升級筆記(適配圖片、通知欄、ContentProvider、Receiver)
Android 8.0 升級筆記 前言 Google 在2017年就釋出了Android 8.0,並且強制AppStore上得應用都要升級,國內得不曉得。為了防止出現之前升級6.0 得時候許可權問題導致Crash這種情況得發生…這次很小心得去看了Google得升級意見,小夥伴們可以自
android 6.0 + 許可權之 打電話
下面看看我怎麼調出去的… 第一步,我們還是要在AndroidManifolest.xml裡面新增 如果你沒有判斷請求許可權會報以下錯誤 AndroidRuntime: FATAL EXCEPTION: main Process: com.example.jie.demo, PI
【Android】Material Design 之四 五 六 AppBarLayout、CoordinatorLayout、CollapsingToolbarLayout使用
一、AppBarLayout AppBarLayout是繼承自LinearLayout,預設是垂直方向,可以看成是一個垂直方向的線性佈局,其作用是將APPBarLayout包裹的內容都作為AppBar,支援手勢滑動。 AppBarLayout必須作為Toolbar的父佈局
Android View原理解析之基礎知識(MeasureSpec、DecorView、ViewRootImpl)
提示:本文的原始碼均取自Android 7.0(API 24) 前言 自定義View是Android進階路線上必須攻克的難題,而在這之前就應該先對View的工作原理有一個系統的理解。本系列將分為4篇部落格進行講解,本文將主要對MeasureSpec、DecorV
Android自學筆記之 Android五大布局之線性佈局的功能、常用屬性、用法
1.介紹: 線性佈局管理器對存放其中的控制元件或佈局採用線性方式管理 2.LinearLayout的常用屬性android:orientation = “vertical” —— 該屬性決定它子類
Android 5.0學習之動畫
前言 使用者跟你的App進行互動時,Material Design中的動畫給予使用者動作的反饋和提供視覺的一致感。 包括之前我學習過的: 除我們已經學習過的動畫之外,Material Design還給我們提供了什麼動畫? Touch feedback(觸控反饋)Rev
Android-Android程序間通訊之messenger
轉自‘https://www.cnblogs.com/makaruila/p/4869912.html 平時一說程序間通訊,大家都會想到AIDL,其實messenger和AIDL作用一樣,都可以進行程序間通訊。它是基於訊息的程序間通訊,就像子執行緒和UI執行緒傳送訊息那樣,是不是很簡單,還不用去寫AIDL檔
[心得]Android程序間通訊之Broadcast Receiver
Android框架層提供的一些通訊機制Broadcast、Intent、Content Provider,主要用於應用程式開發時提供跨程序或應用程式內部的通訊。 android中,通過廣播(broadcast)可以通知廣播接受者某個事件發生了。比如一些系統時間:電源不足,
Android下jni開發之ndk的使用(下載、配置、編譯遇到的問題)
Android下jni開發之ndk的使用 一、簡介 JNI和NDK很多Android開發初學者沒有搞明白這個問題,JNI是Java呼叫Native機制,是Java語言自己的特性全稱為Java Native Interface,類似的還
Android程序間通訊之Socket
Socket也稱為“套接字”,是網路通訊中的概念,它分為流式套接字和使用者資料報套接字兩種,分別對應於網路傳輸控制層中的TCP和UDP協議。 TCP協議是面向連線的協議,提供穩定的雙向通訊功能,TCP連線的建立需要經過“三次握手”才能完成,為了提供穩定的資料傳輸功能,其本身
Android 6.0 PowerManagerService 之 updatePowerStateLocked函式
updatePowerStateLocked /** * Updates the global power state based on dirty bits recorded in mDirty. * * This is the main
android從零單排之手機通訊錄的讀取、新增、刪除、查詢
工作中牽扯到了對android手機通訊錄的系列操作,網上查找了好多資料,大多數都介紹的是模模糊糊,終於找到了一篇靠譜的,於是摘抄下來,大家共同學習:</span> Android聯絡人資料庫檔案(contact2.db) 有研究過手機通訊錄資料的童鞋肯定
Android 5.0學習之Activity過渡動畫
前言 Activity Transition: 提供了三種Transition型別: 進入:一個進入的過渡(動畫)決定activity中的所有的檢視怎麼進入螢幕。退出:一個退出的過渡(動畫)決定一個activity中的所有檢視怎麼退出螢幕。 共享元素:一個共享元素
Android 8.0 特性之 NotificationChannel
在 Android 8.0 中,為 Notification 設定 led,震動,鈴聲時,若按照以前的方法,在發出通知的時候,會出現一行 Toast 資訊: ...Failed to post notification on channel "null"... 這是由於在
Android 5.0學習之Activity共享元素過渡動畫
轉自:http://blog.csdn.net/ljx19900116/article/details/41806889 前言 Activity Transition: 提供了三種Transition型別: 進入:一個進入的過渡(動畫)決定activity中的
KNN演算法身高、體重、鞋號預測男女性別
1.Sklearn程式碼篇 #預測男女性別 from sklearn.neighbors import KNeighborsClassifier import numpy as np neigh=KNeighborsClassifier(n_neighbors=3) # 訓練資料 根據身
Android外掛化開發之AMS與應用程式(客戶端ActivityThread、Instrumentation、Activity)通訊模型分析
今天主要分析下ActivityManagerService(服務端) 與應用程式(客戶端)之間的通訊模型,在介紹這個通訊模型的基礎上,再 簡單介紹實現這個模型所需要資料型別。 本文所介紹內容基於android2.2版本。由於Android版本的不同
Android 藍芽開發之搜尋、配對、連線、通訊大全
藍芽( Bluetooth®):是一種無線技術標準,可實現固定裝置、移動裝置和樓宇個人域網之間的短距離資料交換(使用2.4—2.485GHz的ISM波段的UHF無線電波)。藍芽裝置最多可以同時和7個其它藍芽裝置建立連線,進行通訊,當然並不是每一個藍芽都可以達到
Android進階——Android跨程序通訊機制之Binder、IBinder、Parcel、AIDL
前言 Binder機制是Android系統提供的跨程序通訊機制,這篇文章開始會從Linux相關的基礎概念知識開始介紹,從基礎概念知識中引出Binder機制,歸納Binder機制與Linux系統的跨程序機制的優缺點,接著分析Binder的通訊模型和原理,而Bin