1、大家都知道Android中进程间的通信是通过binder来实现的,这里主要是讲代码中的简单实现。如果想了解binder的通信细节或实现原理,可以参考https://blog.csdn.net/jmq_0000/article/details/7349844。个人觉得这篇博客讲的还是很不错的。现在就开始demo的介绍,该demo主要是通过java传递文件路径给C++来实现删除该路径,目的是为了了解java跟C++是怎么通过binder来通信的。首先是介绍C++端的代码,目录结构如下:

主要是四个文件Android.mk、DeleteFile.cpp、DeleteFile.h、DeleteFileService.cpp。先看一下头文件DeleteFile.h的里面的内容 

 1 #ifndef _DELETE_FILE  2 #define _DELETE_FILE  3  4 #include   5 #include   6 #include   7 #include   8 #include   9 #include  10 #include  11 12 #define LOG_TAG "JPEG_JNI" 13 #define DEBUG 14 #define ANDROID_PLATFORM 15 16 #ifdef DEBUG 17         #ifdef ANDROID_PLATFORM 18                 #define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) 19                 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)) 20                 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)) 21                 #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) 22 23 24         #else 25                 #define LOGD(fmt, ...) printf(fmt"\n", ##__VA_ARGS__) 26                 #define LOGI(fmt, ...) printf(fmt"\n", ##__VA_ARGS__) 27                 #define LOGW(fmt, ...) printf(fmt"\n", ##__VA_ARGS__) 28                 #define LOGE(fmt, ...) printf(fmt"\n", ##__VA_ARGS__) 29         #endif 30 #else 31         #define LOGD(...); 32         #define LOGI(...); 33         #define LOGW(...); 34         #define LOGE(...); 35 #endif 36 38 namespace android{ 39         class DeleteFile: public BBinder{ 40         public: 41                 static int instantiate(); 42                 DeleteFile(); 43                 virtual ~DeleteFile(); 44                 virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t); 45         }; 46 }//namespace 47 48 #endif 37

 头文件里面是主要定义Android的LOG打印及删除文件DeleteFile类的定义及方法声明。DeleteFile类中有四个方法,主要用的是instantiate()跟onTransact()的方法。看一下这两个方法的实现

27 int DeleteFile::instantiate(){ 28         int r = defaultServiceManager()->addService(String16(SERVICE_NAME), new DeleteFile()); 29         return r; 30 } 31 32 status_t DeleteFile::onTransact(uint32_t code, const Parcel& data, Parcel* reply, 33                 uint32_t flags) { 34         switch (code) { 35         case DELETE_FILE:{ 36 //              int keep = data.readInt32(); 37                 String16 path = data.readString16(); 38                 LOGD("[%s(L:%d)] path = %s\n", __FUNCTION__, __LINE__, String8(path).string()); 39                 int result = dealDeleteFiles(String8(path).string()); 40                 reply->writeInt32(result); 41                 system("sync"); 42                 return 0; 43         } 44         break; 45         default: { 46                         return BBinder::onTransact(code, data, reply, flags); 47                 } 48                         break; 49         } 50 }

instantiate() 方法主要是向defaultServiceManager中添加自己定义的服务,服务的名称是chinatsp.autoaction。而onTransact()就是真正通信的方法,在服务启动的情况下,C++中的onTransact()方法跟Java中的binder.transact(cmd, data, reply, 0)进行通信的。方法中code跟data是java中的transact里面的cmd跟data传递过来的,dealDeleteFiles(String8(path).string())方法是实现删除java端传递过来的指定目录的,它的实现非常简单,就是通过rm -rf path 命令删除目录。

12 int dealDeleteFiles(const char* path){ 13         char* cmd = (char*) malloc(16 + strlen(path)); 14         memset(cmd, 0, sizeof(cmd)); 15         sprintf(cmd, "rm -rf %s", path); 16         int result = system(cmd); 17         free(cmd); 18         return result; 19 }

DeleteFile.cpp完整代码如下:

1 #include "DeleteFile.h"  2 #include   3 #include   4 #include   5 #include   6 #include   7 #include   8  9 #define DELETE_FILE 0x01 10 #define SERVICE_NAME "chinatsp.autoaction" 11 12 int dealDeleteFiles(const char* path){ 13         char* cmd = (char*) malloc(16 + strlen(path)); 14         memset(cmd, 0, sizeof(cmd)); 15         sprintf(cmd, "rm -rf %s", path); 16         int result = system(cmd); 17         free(cmd); 18         return result; 19 } 20 21 namespace android{ 22 DeleteFile::DeleteFile(){ 23 } 24 DeleteFile::~DeleteFile(){ 25 26 } 27 int DeleteFile::instantiate(){ 28         int r = defaultServiceManager()->addService(String16(SERVICE_NAME), new DeleteFile()); 29         return r; 30 } 3132 status_t DeleteFile::onTransact(uint32_t code, const Parcel& data, Parcel* reply, 33                 uint32_t flags) { 34         switch (code) { 35         case DELETE_FILE:{ 36 //              int keep = data.readInt32(); 37                 String16 path = data.readString16(); 38                 LOGD("[%s(L:%d)] path = %s\n", __FUNCTION__, __LINE__, String8(path).string()); 39                 int result = dealDeleteFiles(String8(path).string()); 40                 reply->writeInt32(result); 41                 system("sync"); 42                 return 0; 43         } 44         break; 45         default: { 46                         return BBinder::onTransact(code, data, reply, flags); 47                 } 48                         break; 49         } 50 } 51 52 }//namespace

接下来再看一下DeleteFileService.cpp的代码实现:

 1 #include   2 #include   3 #include   4 #include   5 #include   6 #include   7 #include   8 #include "DeleteFile.h"  9 10 using namespace android; 11 int main(int argc, char** argv) 12 { 13         LOGD("main begin....."); 14         LOGD("[%s(L:%d)] \n", __FUNCTION__, __LINE__); 15         sp proc(ProcessState::self()); 16         sp sm = defaultServiceManager(); //取得 ServiceManager 17         DeleteFile::instantiate(); 18         ProcessState::self()->startThreadPool(); //启动缓冲池 19         IPCThreadState::self()->joinThreadPool(); //这里是把服务添加到 Binder闭合循环进程中 20         LOGD("main end....."); 21 }

可以看到main函数里面只有5行的关键代码,15-19中只有17行是自己定义的方法,其他都是binder绑定服务需要调用的。最后一个文件Android.mk也很简单 ,就不做介绍了,代码如下:

 1 LOCAL_PATH:= $(call my-dir)  2  3 include $(CLEAR_VARS)  4  5 LOCAL_SRC_FILES:= DeleteFile.cpp DeleteFileService.cpp  6 LOCAL_C_INCLUDES := \  7         DeleteFile.h \  8         $(JNI_H_INCLUDE)  9 LOCAL_SHARED_LIBRARIES := \ 10         liblog \ 11         libutils \ 12         libandroid_runtime \ 13         libbinder \ 14         libcutils 15 LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog 16 LOCAL_MODULE:= tspautoservice 17 include $(BUILD_EXECUTABLE)

到这里C++端的代码就介绍完了,接下在就是Java端的代码了,主要涉及两个java类及一个布局文件:

java端的界面布局backup_log_fragment.xml很简单,只有一个Button。

<?xml version="1.0" encoding="utf-8"?>    

BackupLogsFragment.java类主要是点击事件及 DeleteLogsTask异步实现删除目录路径传递,这里要删除的是/data/media目录(data目录下的medai目录)

package com.gunder.tool.fragment;import android.os.AsyncTask;import android.os.Bundle;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.View.OnClickListener;import android.view.ViewGroup;import android.widget.Button;import android.widget.Toast;import com.gunder.tool.R;import com.gunder.tool.utils.Logger;import com.gunder.tool.utils.TLogUtils;public class BackupLogsFragment extends Fragment implements OnClickListener{Button deleteLog;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {return inflater.inflate(R.layout.backup_log_fragment, container, false);}@Overridepublic void onViewCreated(View view,  Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);initView(view);}private void initView(View root) {deleteLog = (Button) root.findViewById(R.id.delelte_log);deleteLog.setOnClickListener(this);}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.delelte_log:deleteLogs();break;default:break;}}//开始删除日志private void deleteLogs(){ final String delete_path = "/data/media"; new DeleteLogsTask().execute(delete_path);}private class DeleteLogsTask extends AsyncTask{@Overrideprotected void onPreExecute() {super.onPreExecute();Toast.makeText(getActivity(), "delete file ...", Toast.LENGTH_LONG).show();}@Overrideprotected String doInBackground(String... params) {boolean result = true;String path = params[0];Logger.d("path = " + path);boolean ret = deleteLog(path);result = result && ret;return result ? "success" : "failed";}protected boolean deleteLog(String path){Logger.d();return TLogUtils.deleteLog(path);}@Overrideprotected void onPostExecute(String result) {super.onPostExecute(result);Toast.makeText(getActivity(), "delete " + result, Toast.LENGTH_LONG).show();}}}

 BackupLogsFragment.java类中的实行流程大概如下onClick-->deleteLogs-->doInBackground-->deleteLog-->TLogUtils.deleteLog,发现最后会执行TLogUtils类中的deleteLog静态方法,现在来看一下TLogUtils类中的代码:

package com.gunder.tool.utils;import java.io.File;import android.os.IBinder;import android.os.Parcel;import android.os.ServiceManager;import android.os.SystemProperties;public class TLogUtils {//向C++中传递cmd命令,C++对应的参数是codeprivate final static int DELETE_FILES = 0x1;//如果文件存在,就执行deleteLog方法public static boolean deleteLog(String src){Logger.d("src = " + src);if (null == src){return false;}String path = src;while ((!path.isEmpty()) && path.charAt(path.length() - 1) == '/'){path = path.substring(0, path.length() - 1);}path = path.trim();Logger.d("path = " + path);if (path.isEmpty()){Logger.d("path is empty");return true;}boolean result = false;File file = new File(path);if (file.exists()){result = deleteLogFiles(file);}else {result = true;}if (!result){Logger.d("delete log failed: " + src);}return result;}//如果文件是目录,执行deleteLogFilesUseRoot,否则直接file.delete()private static boolean deleteLogFiles(File file) {Logger.d();if (file != null && file.exists()){Logger.d();if (file.isDirectory()){Logger.d();return deleteLogFilesUseRoot(file.getAbsolutePath());}}else {Logger.d();return file.delete();}return true;}//对要删除的路径进行Parcel写入private static boolean deleteLogFilesUseRoot(String absolutePath) {Logger.d("absolutePath = " + absolutePath);Parcel data = Parcel.obtain();data.writeString(absolutePath);return dealUseRoot(DELETE_FILES, data);}/** * 启动chinatsp.autoaction服务,并且调用binder.transact向C++中的onTransact进行通信 * @param cmd 传递命令,这里是DELETE_FILES = 0x1,跟C++端的定义是一样的 * @param data 传递路径,这里是/data/media * @return */private static boolean dealUseRoot(int cmd, Parcel data) {IBinder binder = null;final int MAX_WAIT = 9; //最多获取service 10次int index = 0;SystemProperties.set("ctl.start", "tsp_auto_service");do {Logger.d("get service : chinatsp.autoaction");binder = ServiceManager.getService("chinatsp.autoaction");if (null == binder){try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}}}while ((null == binder) && ((index++) < MAX_WAIT));if (null == binder){Logger.d("get service of autoaction failed");data.recycle();SystemProperties.set("ctl.stop", "tsp_auto_service");return false;}Parcel reply = Parcel.obtain();int result = -1;try {Logger.d("cmd = " + cmd);binder.transact(cmd, data, reply, 0);result = reply.readInt();} catch (Exception e) {Logger.d("send cmd to autoaction service : error");}data.recycle();reply.recycle();SystemProperties.set("ctl.stop", "tsp_auto_service");return result == 0;}}

 TLogUtils类中实行流程是这样的:deleteLog-->deleteLogFiles-->deleteLogFilesUseRoot-->dealUseRoot。具体代码相信大家可以看懂。最后需要在init.rc中配置一下自定义的服务chinatsp.autoaction的对应的可执行文件tspautoservice,不然调用SystemProperties.set("ctl.start", "tsp_auto_service")不会启动服务。init.rc配置如下:

245 service tsp_auto_service /system/bin/tspautoservice246     class main247     disabled

好了,到这里就介绍完了。

项目的编译可以参考:https://blog.csdn.net/u013357557/article/details/81411686

完整的代码路径:https://github.com/gunder1129/android-tool/tree/master/ToolTemplate 

 

 

更多相关文章

  1. Android(安卓)异步更新UI----handler+thread
  2. Android(安卓)数据库的简单使用
  3. Android(安卓)调试神器-Stetho(Facebook出品)的使用
  4. Android(安卓)中如何调节 TextView 的字间距
  5. Android(安卓)Thread线程
  6. apk分享: Android应用更换皮肤功能的实现思路教程。
  7. Android(安卓)彻底关闭WebView,防止WebView造成OOM
  8. 旅行青蛙(旅かえる)逆向笔记
  9. Android: 如何打开assets or raw文件夹下的数据库文件

随机推荐

  1. ClassLoader解析——Android篇
  2. Android RIL
  3. Android 开发中的日常积累
  4. Android黑科技动态加载(三)之动态加载资
  5. Android保证service不被杀掉-增强版: 进
  6. android 样式表-selector
  7. android apk的签名和权限问题
  8. android TextView字体颜色根据焦点点击变
  9. Android里的动画(补间动画,帧动画,属性动画)
  10. Android开发指南-用户界面-绘制视图