基于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",
"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 {
boolean ftpConnect(String ip, String userName, String passWord, int port);
boolean ftpDisconnect();
boolean fileIsExit(String FileName);
boolean uploadToFtpServer(String srcFilePath, String ftpPath);
boolean downLoadFile(String filePath, String downPath);
void putValue(String key, String value);
String getValue(String key);
void registerCallback(IDownloadProcessCallback 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",
"core/java/android/os/IDownloadProcessCallback.aidl",
":keystore_aidl",
...
2.3 Context中增加系统服务常量
frameworks/base/core/java/android/content/Context.java
...
@StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
MBTK_NETWORK_SERVICE,
WINDOW_SERVICE,
...
public static final String MBTK_NETWORK_SERVICE = "mbtkmanager";
...
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();
}
try {
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);
}
...
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;
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 自定义服务(二)
|