【干货】Android系统定制基础篇:第六部分-Android扩展服务-AndroidX

这篇具有很好参考价值的文章主要介绍了【干货】Android系统定制基础篇:第六部分-Android扩展服务-AndroidX。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

AndroidX 做为一个后台 Service 应用,开机自动运行,配合系统做一些定制化功能,并且对外提供 API。

主要功能:
● 硬件看门狗代理
● USB Host/Device 切换
● 4G 网络保活
● 系统日志写入文件
● 键值拦截
● 启用应用

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

硬件看门狗代理

硬件看门狗代理主要负责下面几项工作:
● 对外提供看门狗 API,比如:打开关闭看门狗、设置超时时长、获取超时时长、判断看门狗是否打开。
● 定时发送看门狗心跳(喂狗)。
● 恢复看门狗状态(因进入 OTA 升级和用户关机时,会临时关闭看门狗,当升级完成或重新开机需要恢复看门狗状态)。

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.实现下面代码:

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

/**
 * 打开、关闭看门狗
 *
 * @param on
 */
public void toggleWatchdog(boolean on) {
    if (null != mWatchdogService) {
        try {
            if (on) {
                mWatchdogService.openWatchdog();
            } else {
                mWatchdogService.closeWatchdog();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

/**
 * 设置看门狗超时时长
 *
 * @param timeout
 */
public void setWatchdogTimeout(int timeout) {
    if (null != mWatchdogService) {
        try {
            mWatchdogService.setWatchdogTimeout(timeout);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

USB Host/Device 切换

通常为了复用 USB 功能,使同一个 USB 口可以同时做为 Host 和 Device(调试) 口使用,我们可以通过软件来切换功能。

Android 默认提供了切换方法,不同的系统文件路径可能不同,如下:

# 路径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

这里为了提供更统一的方法,我们封装 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.实现下面代码:

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

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

/**
 * 获取当前otg模式
 *
 * @return
 *      0:auto,由硬件决定
 *      1:host,usb模式
 *      2:device,otg调试模式
 */
public String getOtgMode() {
    if (null != mOtgService) {
        try {
            return mOtgService.getOtgMode();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    return "0";
}

4G 网络保活
考虑到一些 4G 模块长时间运行的稳定性,可能会出现 4G 模块工作异常而导致网络断开并无法恢复。为了保证 4G 网络在长时间掉网后能够自行恢复,增加 4G 网络保活服务,当网络长时间掉网并不能自恢复时,直接复位 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.实现下面代码:.

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

/**
 * 打开、关闭4G保活服务
 *
 * @param on
 */
public void toggle4GKeepLive(boolean on) {
    if (null != mModemService) {
        try {
            if (on) {
                mModemService.open4gKeepLive();
            } else {
                mModemService.close4gKeepLive();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

系统日志写入文件

为了方便产品上线后 debug,我们默认将 logcat 日志和内核日志写入文件保存,debug 时可以随时导出分析问题。日志文件采用循环保存,默认最多保存10个日志文件,支持设置,单个日志文件最大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.实现下面代码:

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

/**
 * 打开、关闭日志写入文件
 *
 * @param on true:打开 false:关闭
 */
public void toggleLog2file(boolean on) {
    if (null != mLog2fileService) {
        try {
            if (on) {
                mLog2fileService.openLog2file();
            } else {
                mLog2fileService.closeLog2file();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

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

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

键值拦截

一些支持遥控器操作的产品上,默认只允许管理员使用遥控器操作设备,普通用户只能操作『上下左右』键,当操作其它键时需要先按『NUM_LOCK』键,然后输入预设的密码(默认密码:『上上下下左右左右』)才可以解锁后使用。

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.实现下面代码:

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

/**
 * 打开、关闭键值拦截
 *
 * @param on
 */
public void toggleKeyIntercept(boolean on) {
    if (null != mIKeyInterceptService) {
        try {
            if (on) {
                mIKeyInterceptService.openKeyIntercept();
            } else {
                mIKeyInterceptService.closeKeyIntercept();
            }
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

启用应用

一些产品为了方便作业人员安装测试设备,需要临时停用某些应用,有时会忘记恢复,从而导致后面客户应用无法运行的问题。

该方案在通过属性『ro.enableapps』配置开机后需要自动启用的应用包名,开机后运行Service重新启用之前停用的应用。

关键实现

使用 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』配置应用包名,支持同时配置多个包名,用逗号隔开。例如:文章来源地址https://www.toymoban.com/news/detail-489803.html

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

到了这里,关于【干货】Android系统定制基础篇:第六部分-Android扩展服务-AndroidX的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【干货】Android系统定制基础篇:第十四部分(禁止第三方应用调用系统设置、增加TP配置、增加摄像头镜像设置、增加摄像头默认角度设置、修改默认语言)

    修改文件 frameworksbasecorejavaandroidappActivityManagerNative.java 如下: 属性配置: Android 主板定制过程中经常出现客户需要临时适配各种 TP(包括 USB TP),因此在设置菜单中加入 xy 交换,x 反转,y 反转常用配置,以客户多样性需求。 以下修改基于Android 8.1 SDK,如下: 属性配置

    2024年02月10日
    浏览(26)
  • 【干货】Android系统定制基础篇:第一部分(文件权限、增加信号强度、双路背光控制)

    当需要修改某文件或路径权限时,我们可以在init.rc开机启动某节点添加chmod命令进行修改。但是对于system分区,由于是ro权限,在init.rc使用chmod修改权限无效。需要在文件编译时,对权限进行修改。不同的Android版本改法一样,但是文件所在目录有差异,Android O主要修改文件是

    2024年02月09日
    浏览(33)
  • 【干货】Android系统定制基础篇:第二部分(Launcher3支持键盘切换焦点、开发者模式密码确认、禁止非预装应用安装、配置时间)

    Android Launcher3 默认并不支持键盘操作,无法切换焦点,在一些需要支持键盘或遥控操作的设备中无法使用,因些对 Launcher3 做简单修改,使其支持键盘切换焦点。 在安全性要求比较高的产品中,一般会默认关闭『adb调试』,同时禁止用户打开『adb调试』功能。在Android8.1中默认

    2024年02月10日
    浏览(35)
  • 由于数字化转型对集成和扩展性的要求,定制化需求难以满足,百数低代码服务商该如何破局?

    当政策、技术环境的日益成熟,数字化转型逐步成为企业发展的必选项,企业数字化转型不再是一道选择题,而是决定其生存发展的必由之路。通过数字化转型升级生产方式、管理模式和组织形式,激发内生动力,成为企业顺应时代变化,实现高质量发展的必然选择。 一般来

    2024年02月07日
    浏览(37)
  • Android 11 定制系统全局监听触摸事件接口

    1.定义创建aidl接口(由于需要回调这里优先需要增加一个回调接口 ) frameworksbasecorejavaandroidappIOnTouchListener.aidl package android.app; oneway interface IOnTouchListener {      void onTouchEvent( int action); }   2.新增调用接口 在 base/core/java/android/view/IWindowManager.aidl 修改如下: import android.ap

    2023年04月08日
    浏览(42)
  • Android显示系统SurfaceFlinger详解 超级干货

    本文详细讲解了Android显示系统SurfaceFlinger,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 目录 一、Android系统启动 二、SurfaceFlinger代码剖析[Android 11] 1.【执行文件-surfaceflinger】 2.【动态库-libsurfaceflinger.so】 3. 服务启

    2024年03月14日
    浏览(36)
  • 第六章、坐标轴的定制

    6.1、坐标轴概述 在绘制图表过程中,matplotlib会根据所绘图表的类型决定是否使用坐标系,或者显示哪种类型的坐标系。 坐标轴的结构相同,主要包括轴脊、刻度,其中刻度又可以细分为刻度线和刻度标签,刻度线又可以细分为主刻线和次刻线。坐标轴的各部分均是matplotli

    2024年02月06日
    浏览(26)
  • Android 9.0 系统rom定制之user模式下解除系统进入recovery功能的限制

     在9.0的系统rom定制化开发中,系统中recovery模式功能也是很重要的一部分,而在原生系统中,对于debug模式的产品,可以通过电源键和音量+键进入recovery模式, 但是在user模式下的产品,对于通过这种方式,进入recovery模式就受限制了,防止用户无操作为了产品安全等,不让进

    2024年02月16日
    浏览(35)
  • 基于Android+Django+Python的服饰管理与个性化定制系统的设计与实现

    资源下载地址:https://download.csdn.net/download/sheziqiong/87904742 资源下载地址:https://download.csdn.net/download/sheziqiong/87904742 一、选题的背景和意义 1、课题研究背景 随着移动终端技术和网络技术的飞速发展,人们可以使用移动客户端上网,随时随地从互联网获取信息和服务,解决吃

    2024年03月13日
    浏览(84)
  • Microsoft Dynamics 365 CE 扩展定制 - 7. 安全

    在本章中,我们将介绍以下内容: 构建累积安全角色 配置业务单元层次结构 基于分层位置配置访问 配置和分配字段级安全 组建团队并共享 设置访问团队 对静止数据进行加密以满足FIPS 140-2标准 管理Dynamics 365在线SQLTDE加密密钥 Dynamics 365是一个强大的平台,具有超过10年的良

    2024年02月05日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包