天天看點

Android 上層應用讀寫裝置節點Android 上層應用讀寫裝置節點

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();
                    }
                }
            }
        }
    }