国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【干貨】Android系統(tǒng)定制基礎(chǔ)篇:第六部分-Android擴展服務(wù)-AndroidX

這篇具有很好參考價值的文章主要介紹了【干貨】Android系統(tǒng)定制基礎(chǔ)篇:第六部分-Android擴展服務(wù)-AndroidX。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

AndroidX 做為一個后臺 Service 應(yīng)用,開機自動運行,配合系統(tǒng)做一些定制化功能,并且對外提供 API。

主要功能:
● 硬件看門狗代理
● USB Host/Device 切換
● 4G 網(wǎng)絡(luò)保活
● 系統(tǒng)日志寫入文件
● 鍵值攔截
● 啟用應(yīng)用

項目地址:https://github.com/aystshen/AndroidX

硬件看門狗代理

硬件看門狗代理主要負責(zé)下面幾項工作:
● 對外提供看門狗 API,比如:打開關(guān)閉看門狗、設(shè)置超時時長、獲取超時時長、判斷看門狗是否打開。
● 定時發(fā)送看門狗心跳(喂狗)。
● 恢復(fù)看門狗狀態(tài)(因進入 OTA 升級和用戶關(guān)機時,會臨時關(guān)閉看門狗,當(dāng)升級完成或重新開機需要恢復(fù)看門狗狀態(tài))。

API

// IWatchdogService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IWatchdogService {
    boolean openWatchdog();
    boolean closeWatchdog();
    boolean setWatchdogTimeout(int timeout);
    int getWatchdogTimeout();
    boolean watchdogIsOpen();
}

使用

1、在 APP 源碼 aidl/android/os/ 目錄下新建 IWatchdogService.aidl,如下:

// IWatchdogService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IWatchdogService {
    boolean openWatchdog();
    boolean closeWatchdog();
    boolean setWatchdogTimeout(int timeout);
    int getWatchdogTimeout();
    boolean watchdogIsOpen();
}

2.實現(xiàn)下面代碼:

Intent intent = new Intent();
intent.setPackage("com.ayst.androidx");
intent.setAction("com.ayst.androidx.WATCHDOG_SERVICE");
mContext.bindService(intent, mWatchdogServiceConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mWatchdogServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "IWatchdogService, onServiceConnected...");
        mWatchdogService = IWatchdogService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "IWatchdogService, onServiceDisconnected...");
        mWatchdogService = null;
    }
};

/**
 * 打開、關(guān)閉看門狗
 *
 * @param on
 */
public void toggleWatchdog(boolean on) {
    if (null != mWatchdogService) {
        try {
            if (on) {
                mWatchdogService.openWatchdog();
            } else {
                mWatchdogService.closeWatchdog();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 設(shè)置看門狗超時時長
 *
 * @param timeout
 */
public void setWatchdogTimeout(int timeout) {
    if (null != mWatchdogService) {
        try {
            mWatchdogService.setWatchdogTimeout(timeout);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

USB Host/Device 切換

通常為了復(fù)用 USB 功能,使同一個 USB 口可以同時做為 Host 和 Device(調(diào)試) 口使用,我們可以通過軟件來切換功能。

Android 默認提供了切換方法,不同的系統(tǒng)文件路徑可能不同,如下:

# 路徑1,向下面文件寫入:0:自動,1:HOST,2:OTG
/sys/bus/platform/drivers/usb20_otg/force_usb_mode

# 路徑2, 向下面文件寫入:peripheral:自動,host:HOST,otg:OTG
/sys/devices/platform/ff770000.syscon/ff770000.syscon:usb2-phy@e450/otg_mode

這里為了提供更統(tǒng)一的方法,我們封裝 Java API。

API

// IOtgService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IOtgService {
    boolean setOtgMode(String mode);
    String getOtgMode();
}

1、使用
在 APP 源碼 aidl/android/os/ 目錄下新建 IOtgService.aidl,如下:

// IOtgService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IOtgService {
    boolean setOtgMode(String mode);
    String getOtgMode();
}

2.實現(xiàn)下面代碼:

Intent intent = new Intent();
intent.setPackage("com.ayst.androidx");
intent.setAction("com.ayst.androidx.OTG_SERVICE");
mContext.bindService(intent, mOtgServiceConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mOtgServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "IOtgService, onServiceConnected...");
        mOtgService = IOtgService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "IOtgService, onServiceDisconnected...");
        mOtgService = null;
    }
};

/**
 * 調(diào)otg口usb工作模式
 *
 * @param mode
 *      0:auto,由硬件決定
 *      1:host,usb模式
 *      2:device,otg調(diào)試模式
 */
public void setOtgMode(String mode) {
    if (null != mOtgService) {
        try {
            if (!mOtgService.setOtgMode(mode)) {
                mAndroidXView.updateAndroidXOtgMode(mOtgService.getOtgMode());
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 獲取當(dāng)前otg模式
 *
 * @return
 *      0:auto,由硬件決定
 *      1:host,usb模式
 *      2:device,otg調(diào)試模式
 */
public String getOtgMode() {
    if (null != mOtgService) {
        try {
            return mOtgService.getOtgMode();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    return "0";
}

4G 網(wǎng)絡(luò)?;?/strong>
考慮到一些 4G 模塊長時間運行的穩(wěn)定性,可能會出現(xiàn) 4G 模塊工作異常而導(dǎo)致網(wǎng)絡(luò)斷開并無法恢復(fù)。為了保證 4G 網(wǎng)絡(luò)在長時間掉網(wǎng)后能夠自行恢復(fù),增加 4G 網(wǎng)絡(luò)?;罘?wù),當(dāng)網(wǎng)絡(luò)長時間掉網(wǎng)并不能自恢復(fù)時,直接復(fù)位 4G 模塊,使 4G 模塊重啟工作。

API

// IModemService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IModemService {
    boolean open4gKeepLive();
    boolean close4gKeepLive();
    boolean keepLiveIsOpen();
}

1.在 APP 源碼 aidl/android/os/ 目錄下新建 IModemService.aidl,如下:

// IModemService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IModemService {
    boolean open4gKeepLive();
    boolean close4gKeepLive();
    boolean keepLiveIsOpen();
}

2.實現(xiàn)下面代碼:.

Intent intent = new Intent();
intent.setPackage("com.ayst.androidx");
intent.setAction("com.ayst.androidx.MODEM_SERVICE");
mContext.bindService(intent, mModemServiceConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mModemServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "IModemService, onServiceConnected...");
        mModemService = IModemService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "IModemService, onServiceDisconnected...");
        mModemService = null;
    }
};

/**
 * 打開、關(guān)閉4G?;罘?wù)
 *
 * @param on
 */
public void toggle4GKeepLive(boolean on) {
    if (null != mModemService) {
        try {
            if (on) {
                mModemService.open4gKeepLive();
            } else {
                mModemService.close4gKeepLive();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

系統(tǒng)日志寫入文件

為了方便產(chǎn)品上線后 debug,我們默認將 logcat 日志和內(nèi)核日志寫入文件保存,debug 時可以隨時導(dǎo)出分析問題。日志文件采用循環(huán)保存,默認最多保存10個日志文件,支持設(shè)置,單個日志文件最大20M。

日志路徑:/sdcard/lastlog/

cnnho:/sdcard/lastlog/android $ ls -l
total 12880
-rw-rw---- 1 root sdcard_rw 1288359 2020-03-02 17:26 2020-03-02_17-23-09.log
-rw-rw---- 1 root sdcard_rw 1301092 2020-03-02 17:31 2020-03-02_17-26-44.log
-rw-rw---- 1 root sdcard_rw 1466984 2020-03-02 17:40 2020-03-02_17-32-23.log
-rw-rw---- 1 root sdcard_rw 1212094 2020-03-02 17:43 2020-03-02_17-41-11.log
-rw-rw---- 1 root sdcard_rw 1328673 2020-03-02 17:49 2020-03-02_17-44-05.log
-rw-rw---- 1 root sdcard_rw 2403373 2020-03-02 18:38 2020-03-02_17-50-00.log
-rw-rw---- 1 root sdcard_rw   79347 2020-03-02 18:41 2020-03-02_18-38-16.log
-rw-rw---- 1 root sdcard_rw 1292712 2020-03-02 18:53 2020-03-02_18-49-41.log
-rw-rw---- 1 root sdcard_rw 1567416 2020-03-02 19:06 2020-03-02_18-53-59.log
-rw-rw---- 1 root sdcard_rw 1227984 2020-03-02 19:09 2020-03-02_19-07-29.log

API

// ILog2fileService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface ILog2fileService {
    void openLog2file();
    void closeLog2file();
    boolean isOpen();
    boolean setLogFileNum(int num);
    int getLogFileNum();
}

1.在 APP 源碼 aidl/android/os/ 目錄下新建 ILog2fileService.aidl,如下:

// ILog2fileService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface ILog2fileService {
    void openLog2file();
    void closeLog2file();
    boolean isOpen();
    boolean setLogFileNum(int num);
    int getLogFileNum();
}

2.實現(xiàn)下面代碼:

Intent intent = new Intent();
intent.setPackage("com.ayst.androidx");
intent.setAction("com.ayst.androidx.LOG2FILE_SERVICE");
mContext.bindService(intent, mLog2fileServiceConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mLog2fileServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "ILog2fileService, onServiceConnected...");
        mLog2fileService = ILog2fileService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "ILog2fileService, onServiceDisconnected...");
        mLog2fileService = null;
    }
};

/**
 * 打開、關(guān)閉日志寫入文件
 *
 * @param on true:打開 false:關(guān)閉
 */
public void toggleLog2file(boolean on) {
    if (null != mLog2fileService) {
        try {
            if (on) {
                mLog2fileService.openLog2file();
            } else {
                mLog2fileService.closeLog2file();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 設(shè)置最大保存日志文件數(shù)
 *
 * @param num 最大日志文件數(shù)
 * @return true:成功 false:失敗
 */
private boolean setLogFileNum(int num) {
    if (null != mLog2fileService) {
        try {
            return mLog2fileService.setLogFileNum(num);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    return false;
}

/**
 * 獲取最大保存日志文件數(shù)
 *
 * @return 最大日志文件數(shù)
 */
private int getLogFileNum() {
    if (null != mLog2fileService) {
        try {
            return mLog2fileService.getLogFileNum();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
    return 0;
}

鍵值攔截

一些支持遙控器操作的產(chǎn)品上,默認只允許管理員使用遙控器操作設(shè)備,普通用戶只能操作『上下左右』鍵,當(dāng)操作其它鍵時需要先按『NUM_LOCK』鍵,然后輸入預(yù)設(shè)的密碼(默認密碼:『上上下下左右左右』)才可以解鎖后使用。

API

// IKeyInterceptService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IKeyInterceptService {
    void openKeyIntercept();
    void closeKeyIntercept();
    boolean isOpen();
}

使用
1.在 APP 源碼 aidl/android/os/ 目錄下新建 IKeyInterceptService.aidl,如下:

// IKeyInterceptService.aidl
package com.ayst.androidx;

// Declare any non-default types here with import statements

interface IKeyInterceptService {
    void openKeyIntercept();
    void closeKeyIntercept();
    boolean isOpen();
}

2.實現(xiàn)下面代碼:

Intent intent = new Intent();
intent.setPackage("com.ayst.androidx");
intent.setAction("com.ayst.androidx.KEY_INTERCEPT_SERVICE");
mContext.bindService(intent, mKeyInterceptServiceConnection, Context.BIND_AUTO_CREATE);

private ServiceConnection mKeyInterceptServiceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.d(TAG, "IKeyInterceptService, onServiceConnected...");
        mIKeyInterceptService = IKeyInterceptService.Stub.asInterface(service);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        Log.d(TAG, "IKeyInterceptService, onServiceDisconnected...");
        mIKeyInterceptService = null;
    }
};

/**
 * 打開、關(guān)閉鍵值攔截
 *
 * @param on
 */
public void toggleKeyIntercept(boolean on) {
    if (null != mIKeyInterceptService) {
        try {
            if (on) {
                mIKeyInterceptService.openKeyIntercept();
            } else {
                mIKeyInterceptService.closeKeyIntercept();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

啟用應(yīng)用

一些產(chǎn)品為了方便作業(yè)人員安裝測試設(shè)備,需要臨時停用某些應(yīng)用,有時會忘記恢復(fù),從而導(dǎo)致后面客戶應(yīng)用無法運行的問題。

該方案在通過屬性『ro.enableapps』配置開機后需要自動啟用的應(yīng)用包名,開機后運行Service重新啟用之前停用的應(yīng)用。

關(guān)鍵實現(xiàn)

使用 PackageManager 提供的方法:

/**
 * Set the enabled setting for an application
 * This setting will override any enabled state which may have been set by the application in
 * its manifest.  It also overrides the enabled state set in the manifest for any of the
 * application's components.  It does not override any enabled state set by
 * {@link #setComponentEnabledSetting} for any of the application's components.
 *
 * @param packageName The package name of the application to enable
 * @param newState The new enabled state for the application.
 * @param flags Optional behavior flags.
 */
public abstract void setApplicationEnabledSetting(String packageName,
        @EnabledState int newState, @EnabledFlags int flags);
public class AppEnableService extends Service {
    private static final String TAG = "AppEnableService";

    private String[] mEnableApps;
    private Thread mEnableThread;

    public AppEnableService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand...");

        mEnableApps = loadApps();

        if (null != mEnableApps && mEnableApps.length > 0) {
            mEnableThread = new Thread(mEnableRunnable);
            mEnableThread.start();
        } else {
            Log.w(TAG, "onStartCommand, There is no application to be enabled.");
        }

        return Service.START_REDELIVER_INTENT;
    }

    private String[] loadApps() {
        String value = AppUtils.getProperty("ro.enableapps", "");
        if (!TextUtils.isEmpty(value)) {
            return value.split(",");
        }

        return null;
    }

    private Runnable mEnableRunnable = new Runnable() {
        @Override
        public void run() {
            PackageManager pm = getPackageManager();
            for (String pkgName : mEnableApps) {
                if (!TextUtils.isEmpty(pkgName)
                && pkgName.contains(".")) {
                    pm.setApplicationEnabledSetting(
                            pkgName,
                            PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
                            0);

                    Log.i(TAG, pkgName + " Enabled.");
                }
            }
        }
    };
}

屬性配置

通過屬性『ro.enableapps』配置應(yīng)用包名,支持同時配置多個包名,用逗號隔開。例如:文章來源地址http://www.zghlxwxcb.cn/news/detail-489803.html

ro.enableapps=com.ayst.sample1,com.ayst.sample2

到了這里,關(guān)于【干貨】Android系統(tǒng)定制基礎(chǔ)篇:第六部分-Android擴展服務(wù)-AndroidX的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包