Android 上層應用讀寫裝置節點
Android L
[TOC]
1. Android 裝置節點
Android基于Linux核心。裝置節點檔案是裝置驅動的邏輯檔案,可以通過裝置節點來通路裝置驅動。
很多裝置資訊都可存儲在節點中。apk可以通路節點,擷取裝置資訊或狀态。
2. framework中讀取節點的例子
Android Settings 應用中給出了很多的裝置資訊,可以以此為入口;進一步可以找到 Build.java
例如擷取裝置的版本号,應用中直接可以調用 Build.DISPLAY 獲得字元串
源碼 Build.java (frameworks\base\core\java\android\os)
public static final String PRODUCT = getString("ro.product.name");
......
private static String getString(String property) {
return SystemProperties.get(property, UNKNOWN);
}
跳轉到 SystemProperties.java (frameworks\base\core\java\android\os) 這個類不開放
// 調用 native_get ,擷取節點;可以設定預設值
public static String get(String key, String def) {
if (key.length() > PROP_NAME_MAX) {
throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
}
return native_get(key, def);
}
3. 應用層讀寫節點
應用層中,一般都能夠讀取裝置節點。對于寫節點這個操作,需要更高的root權限。
讀取裝置節點
例如給裝置新添加了節點,路徑是
/sys/class/demo/version
可以
adb shell
進入機器,然後
cat /sys/class/demo/version
;即可獲得資訊
也可以寫成一個方法,如下:
/**
* 擷取節點
*/
private static String getString(String path) {
String prop = "waiting";// 預設值
try {
BufferedReader reader = new BufferedReader(new FileReader(path));
prop = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return prop;
}
調用方法就是:
getString("/sys/class/demo/version")
寫裝置節點
這裡寫節點的方法需要更高的權限,apk要放到源碼中進行編譯;
源碼中編譯apk的方法如同添加第三方apk的方法
AndroidManifest中添加:
android:sharedUserId="android.uid.system"
寫節點的代碼
private static final String WAKE_PATH = "/sys/class/demo/wake";
......
try {
BufferedWriter bufWriter = null;
bufWriter = new BufferedWriter(new FileWriter(WAKE_PATH));
bufWriter.write("1"); // 寫操作
bufWriter.close();
Toast.makeText(getApplicationContext(),
"功能已激活",Toast.LENGTH_SHORT).show();
Log.d(TAG,"功能已激活 angle " + getString(ANGLE_PATH));
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"can't write the " + WAKE_PATH);
}
經過源碼mm編譯後,push到裝置中可以檢視效果
定時讀取裝置節點
需要被更新的View記得調用
invalidate()
方法
使用定時器與Handler來定時讀取節點,并更新UI
重新開機定時器和取消定時器都封裝成方法,便于調用
Timer mTimer;
TimerTask mTimerTask;
SensorHandler mHandler = new SensorHandler(this);
/**
* Handler : update value
*/
static class SensorHandler extends Handler {
MainActivity mainActivity;
SensorHandler(MainActivity activity) {
mainActivity = activity;
}
@Override
public void handleMessage(Message msg) {
mainActivity.ultrasoundValue.setText(getString(ULTRASOUND_VALUE_PATH));
}
}
......
/**
* cancel timer and timer task
*/
private void cancelUltrasoundTimer(){
if (mTimer != null) {
mTimer.cancel();
mTimer = null;
}
if (mTimerTask != null){
mTimerTask.cancel();
mTimerTask = null;
}
}
/**
* restart timer to update UI
*/
private void restartUltrasoundTimer(String timer){
cancelUltrasoundTimer();
mTimer = new Timer(timer);
mTimerTask = new TimerTask() {
@Override
public void run() {
mHandler.sendEmptyMessageAtTime(1300, 50);
}
};
mTimer.schedule(mTimerTask, 50, 50);
}
使用 Runnable 和 Handler 來定時更新UI
Handler 部分不變,在開啟的子線程中向Handler發送消息
onCreate 方法中啟動子線程
Thread t = new Thread(new UpdateUIThread());
t.start();
class UpdateUIThread implements Runnable {
@Override
public void run() {
while (true) {
while (ultraStatus) {
Message message = new Message();
message.what = UPDATE_ULTRA_VALUE;// int
mHandler.sendMessage(message);
try {
Thread.sleep(100); // 暫停100ms,起到定時的效果
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}