IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 9.0 自定义服务(一) -> 正文阅读

[移动开发]Android 9.0 自定义服务(一)

基于FTP下载功能,需要整合 commons-net-3.8.0.jar ,自定义一个服务

commons-net-3.8.jar : Apache Commons Net 阿帕奇提供的常用的网络交互的jar包。
下载地址:https://download.csdn.net/download/lshcsdn/9937674
支持以下协议:

  • FTP/FTPS
  • FTP over HTTP (experimental)
  • NNTP
  • SMTP(S)
  • POP3(S)
  • IMAP(S)
  • Telnet
  • TFTP
  • Finger
  • Whois
  • rexec/rcmd/rlogin
  • Time (rdate) and Daytime
  • Echo
  • Discard
  • NTP/SNTP

第一步 : 导第三方包

1. 将JAR 包导入安卓系统

代码路径 :frameworks/base/libs/FTP

1.1 新建一个文件夹 FTP

将 commons-net-3.8.0.jar 复制进去

1.2 再在FTP文件夹下新建 Android.bp

java_import {
    name: "commons-net-3.8.0_jar",
    jars: ["commons-net-3.8.0.jar"],
}

1.3 在 frameworks/base/Android.bp 添加

    static_libs: [
        "commons-net-3.8.0_jar",//添加到 static_libs 中
        "framework-protos",
        "android.hidl.base-V1.0-java",
        "android.hardware.cas-V1.0-java",
        "android.hardware.contexthub-V1.0-java",
    ],

1.4 尝试编译 framework

make framework -j8

一般不会有错,只需要注意 FTP 下的 Android.bp “jars” 属性,路径是否正确

第二步: 创建服务

2 添加服务代码

2.1 编写aidl接口文件

/frameworks/base/core/java/android/os/IMbtkNetworkService.aidl

package android.os;

import android.os.IDownloadProcessCallback;

interface IMbtkNetworkService {
    // 连接ftp
    boolean ftpConnect(String ip, String userName, String passWord, int port);
    // 断开ftp连接
    boolean ftpDisconnect();

    // 判断文件在服务器上是否存在(遍历) 返回结果
    boolean fileIsExit(String FileName);

    // 上传文件 源文件路径  ftp路径
    boolean uploadToFtpServer(String srcFilePath, String ftpPath);

    // 下载文件
    boolean downLoadFile(String filePath, String downPath);

    // 测试用
    void putValue(String key, String value);
    String getValue(String key);

    // void setCallback(IDownloadListener listener);

    // Register callback
    void registerCallback(IDownloadProcessCallback callback);

    // Unregister callback
    void unregisterCallback(IDownloadProcessCallback callback);

}

2.2 将aidl文件加入到 Android.bp

/frameworks/base/Android.bp

java_library {
    name: "framework",

    srcs: [
        ...
        "core/java/android/os/storage/IObbActionListener.aidl",
        "core/java/android/os/IMbtkNetworkService.aidl", // 添加aidl到系统
        "core/java/android/os/IDownloadProcessCallback.aidl",
        ":keystore_aidl",
        ...

2.3 Context中增加系统服务常量

frameworks/base/core/java/android/content/Context.java

    ...
    /** @hide */
    @StringDef(suffix = { "_SERVICE" }, value = {
            POWER_SERVICE,
            MBTK_NETWORK_SERVICE,// add 
            WINDOW_SERVICE,
    ...
    public static final String MBTK_NETWORK_SERVICE = "mbtkmanager"; // add 
    ...

2.4 添加 manager类

frameworks/base/core/java/android/app/MbtkNetworkManager.java

package android.app;

import android.content.Context;
import android.os.RemoteException;
import android.os.IMbtkNetworkService;
import android.annotation.SystemService;
import android.util.Slog;
import android.os.IDownloadProcessCallback;

@SystemService(Context.MBTK_NETWORK_SERVICE)
public class MbtkNetworkManager {
    private static String TAG = "MbtkNetworkManager";
    private final IMbtkNetworkService mService;
    private final Context mContext;

    public MbtkNetworkManager(Context context, IMbtkNetworkService service) {
        mContext = context;
        mService = service;
        if (mService != null)
            Slog.d(TAG, "mService not null");
    }

    public boolean ftpConnect(String ip, String userName, String passWord, int port) throws RemoteException {
        return mService.ftpConnect(ip, userName, passWord, port);
    }

    public boolean ftpDisconnect() throws RemoteException {
        return mService.ftpDisconnect();
    }

    public boolean fileIsExit(String fileName) throws RemoteException {
        return mService.fileIsExit(fileName);
    }

    public boolean uploadToFtpServer(String srcFilePath, String ftpPath) throws RemoteException {
        return mService.uploadToFtpServer(srcFilePath, ftpPath);
    }

    public boolean downLoadFile(String ftpFilePath, String downPath) throws RemoteException {
        return mService.downLoadFile(ftpFilePath, downPath);
    }

    public void registerCallback(IDownloadProcessCallback listener) throws RemoteException {
        mService.registerCallback(listener);
    }

    public void unregisterCallback(IDownloadProcessCallback listener) throws RemoteException {
        mService.unregisterCallback(listener);
    }

    public String getValue(String key) {
        try {
            android.util.Log.d(TAG, "NetworkManager getValue " + key);
            return mService.getValue(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public void setValue(String key, String value) {
        try {
            android.util.Log.d(TAG, "NetworkManager setValue " + key + "-->" + value);
            mService.putValue(key, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.5 实现具体服务

frameworks/base/services/core/java/com/android/server/MbtkNetworkService.java

package com.android.server;

import android.os.RemoteException;
import android.os.IMbtkNetworkService;
import android.os.IDownloadProcessCallback;
import java.util.HashMap;
import android.util.Log;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;


public class MbtkNetworkService extends IMbtkNetworkService.Stub {
    static final String TAG = "MbtkNetworkService";
    private FtpUtils mFtpUtil;
    private static HashMap<String, String> map = new HashMap<>();
    private IDownloadProcessCallback mDownloadProcessCallback;

    @Override
    public boolean ftpConnect(String ip, String userName, String passWord, int port) throws RemoteException {
        if (mFtpUtil == null) {
            mFtpUtil = new FtpUtils();
        }
        boolean flag = mFtpUtil.ftpConnect(ip, userName, passWord, port);
        Log.d(TAG, "== flag = " + flag);
        return flag;
    }

    @Override
    public boolean ftpDisconnect() throws RemoteException {
        return mFtpUtil.ftpDisconnect();
    }

    @Override
    public boolean fileIsExit(String FileName) throws RemoteException {
        return false;
    }

    @Override
    public boolean uploadToFtpServer(String srcFilePath, String ftpPath) throws RemoteException {
        return false;
    }

    @Override
    public boolean downLoadFile(String ftpFilePath, String downPath) throws RemoteException {
        boolean result = false;
        try {
            mFtpUtil.setCallback(mDownloadProcessCallback);
            result = mFtpUtil.downLoadFile(ftpFilePath, downPath);
        } catch (Exception e) {
            Log.d(TAG, "Error occurred while downLoadFile from ftp server.");
        }
        return result;
    }

    @Override
    public void registerCallback(IDownloadProcessCallback listener) throws RemoteException {
        if (listener != null) {
            mDownloadProcessCallback = listener;
        }
    }

    @Override
    public void unregisterCallback(IDownloadProcessCallback listener) throws RemoteException {
        if (listener != null) {
            mDownloadProcessCallback = null;
        }
    }

    @Override
    public void putValue(String key, String value) throws RemoteException {
        map.put(key, value);
    }

    @Override
    public String getValue(String key) throws RemoteException {
        return map.get(key);
    }

}

2.6 把服务添加到 systemserver

所有系统服务都运行在名为 system_server 的进程中, 我们要把编写好的服务加进去, SystemServer 中有很多服务, 我们把我们的系统服务加到最后面

frameworks/base/services/java/com/android/server/SystemServer.java

private void startOtherServices() {
    ...
            if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_system", false)) {
            throw new RuntimeException();
        }

        //[Feature] add by zhangzh for MobileNetworkService -- 2022-6-21 [Start]
        try {
            // 这里会存在selinus 权限问题,需要配置
            Slog.i(TAG, "network Service");
            traceBeginAndSlog("StartMbtkNetworkService");
            ServiceManager.addService(Context.MBTK_NETWORK_SERVICE, new MbtkNetworkService());
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        } catch (Throwable e) {
            Slog.i(TAG, "starting MbtkNetworkService", e);
        }
        //[Feature] add by zhangzh for MobileNetworkService -- 2022-6-21 [End]
    ...

2.7 注册 Manager

frameworks/base/core/java/android/app/SystemServiceRegistry.java

添加到 static 块中
static {
    ...
    registerService(Context.MBTK_NETWORK_SERVICE, MbtkNetworkManager.class,
                new CachedServiceFetcher<MbtkNetworkManager>() {
                    @Override
                    public MbtkNetworkManager createService(ContextImpl ctx)
                            throws ServiceNotFoundException {
                        IBinder b = ServiceManager.getServiceOrThrow(Context.MBTK_NETWORK_SERVICE);
                        IMbtkNetworkService service = IMbtkNetworkService.Stub.asInterface(b);
                        MbtkNetworkManager mNetworkManager = new MbtkNetworkManager(ctx, service);
                        return mNetworkManager;
                    }});
}

make update-api

3 Selinux权限

需要注意的是,添加权限在中间部分或者头部,如果添加在末尾,需要在代码末尾保留原本的空行,否则在编译代码的时候会解析出错,会解析到下一个文件的头部去,报语法错误。

3.1 service_contexts

device/qcom/sepolicy/vendor/common/service_contexts

+mbtkmanager                                   u:object_r:mbtknetwork_service:s0

3.2 untrusted_app.te

device/qcom/sepolicy/vendor/common/untrusted_app.te

+allow untrusted_app vendor_gles_data_file:dir search;
+allow untrusted_app mbtknetwork_service:service_manager find;

3.3 nonplat_sepolicy.cil

system/sepolicy/prebuilts/api/26.0/nonplat_sepolicy.cil

+(typeattribute mbtknetwork_service_26_0)
+(roletype object_r mbtknetwork_service_26_0)

system/sepolicy/prebuilts/api/27.0/nonplat_sepolicy.cil

+(typeattribute mbtknetwork_service_27_0)
+(roletype object_r mbtknetwork_service_27_0)

3.4 service_contexts

所有 service_contexts 都添加一样的

system/sepolicy/private/service_contexts

system/sepolicy/prebuilts/api/26.0/private/service_contexts
system/sepolicy/prebuilts/api/27.0/private/service_contexts
system/sepolicy/prebuilts/api/28.0/private/service_contexts

+mbtkmanager                               u:object_r:mbtknetwork_service:s0

3.5 service.te

system/sepolicy/public/service.te

system/sepolicy/prebuilts/api/26.0/public/service.te

system/sepolicy/prebuilts/api/27.0/public/service.te

system/sepolicy/prebuilts/api/28.0/public/service.te

+type mbtknetwork_service, system_api_service, system_server_service, service_manager_type;

3.6 26.0.cil

system/sepolicy/private/compat/26.0/26.0.cil

+(typeattributeset mbtknetwork_service_26_0 (mbtknetwork_service))

system/sepolicy/private/compat/27.0/27.0.cil

+(typeattributeset mbtknetwork_service_27_0 (mbtknetwork_service))

system/sepolicy/prebuilts/api/28.0/private/compat/26.0/26.0.cil

+(typeattributeset mbtknetwork_service_26_0 (mbtknetwork_service))

system/sepolicy/prebuilts/api/28.0/private/compat/27.0/27.0.cil

+(typeattributeset mbtknetwork_service_27_0 (mbtknetwork_service))

3.7 system_server.te

system/sepolicy/private/system_server.te

system/sepolicy/prebuilts/api/28.0/private/system_server.te

+allow system_server mbtknetwork_service:service_manager {add};

4 客户端调用

4.1 系统app

我是直接在源码内置的app中添加了一个activity进行测试的
通过下面的方式来获取manager类,去调用服务。

manager = (MbtkNetworkManager) getSystemService(Context.MBTK_NETWORK_SERVICE);

代码如下:

public class NetworkServiceTestActivity extends Activity implements View.OnClickListener {
    private static String TAG = "NetworkServiceTestActivity";
    private MbtkNetworkManager manager = null;
    // 下面这些就按照自己的ftp信息填就行
    private static final String ip = "xxxxxx";
    private static final int port = xxxxx;
    private static final String userName = "xxxx";
    private static final String password = "xxxx";
    private static final String ftpDir = "xxx";
    private static final String downLoadPath = "xxxx";
    private static final String fileName = "xxxx";
    private Button button;

    public void onCreate(Bundle paramBundle) {
        super.onCreate(paramBundle);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "=== NetworkServiceTestActivity onCreate ===");
        manager = (MbtkNetworkManager) getSystemService(Context.MBTK_NETWORK_SERVICE);
        manager.setValue("hellow", "world");
        // 这里是一段测试从服务获取结果的代码
        Log.d(TAG, "get service value is = " + manager.getValue("hellow") + "");
        button = findViewById(R.id.download);
        button.setOnClickListener(NetworkServiceTestActivity.this);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.download:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        boolean result = false;
                        try {
                            Log.d(TAG, "start ftpConnect");
                            boolean flag = manager.ftpConnect(ip, userName, password, port);
                            Log.d(TAG, "onClick ftpConnect flag = " + flag);
                            if (flag) {
                                Log.d(TAG, "downloadFromFtpServer");
                                try {
                                    Log.d(TAG, "== registerCallback ==");
                                    // 注册下载进度回调
                                    manager.registerCallback(new DownloadProcessCallbackImpl());
                                } catch (RemoteException e) {
                                    e.printStackTrace();
                                }
                                result = manager.downLoadFile(ftpDir, downLoadPath);
                            }
                            if (result) {
                                Log.d(TAG, "==== 文件下载成功 ====");
                            } else {
                                Log.d(TAG, "==== 文件下载失败 ====");
                            }
                            Log.d(TAG, "ftpDisconnect");
                            try {
                                Log.d(TAG, "== unregisterCallback ==");
                                // 取消注册
                                manager.unregisterCallback(new DownloadProcessCallbackImpl());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            manager.ftpDisconnect();
                        } catch (Exception e) {

                        }
                    }
                }).start();
        }
    }

    protected void onDestroy() {
        super.onDestroy();
    }

    class DownloadProcessCallbackImpl extends IDownloadProcessCallback.Stub {
        @Override
        public void onProgress(long process) throws RemoteException {
            Log.d(TAG, "===== 下载进度 : " + process);
        }

        @Override
        public void onSuccess() throws RemoteException {

        }

        @Override
        public void onFailed() throws RemoteException {

        }
    }
}

4.2 第三方app调用

需要将编译出的class.jar 包导入,后才能正常调用

Android 9.0 自定义服务(二)

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 16:34:46  更:2022-07-17 16:35:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 10:19:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码