1.这里主要是在jni中获得类中的成员变量容器,然后添加,遍历完毕,执行对应的函数进行显示。
2主要jni代码如下:
#include <jni.h>
#include <string>
#include "dirent.h"
#include "android/log.h"
using namespace std;
#define TAG "native"
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__))
extern "C"
{
bool isFirst = true;
static int index = 0;
jstring gun(JNIEnv*env , jobject clazz){
std::string test = "JNITest ++++";
return env->NewStringUTF(test.c_str());
}
void showAllFiles(JNIEnv* env,jobject job,string dir_name) {
int i = 0;
if(isFirst){
i=1;
isFirst = false;
}
jclass classT = env->FindClass("com/example/filemanager/MainActivity");
jfieldID jfd = env->GetFieldID(classT,"files", "Ljava/util/ArrayList;");
jmethodID showMid = env->GetMethodID(classT,"showFiles", "()V");
jobject obj = env->GetObjectField(job,jfd);
if(obj==NULL){
LOGE("obj is null hahahah");
}
jclass listClass = env->FindClass("java/util/ArrayList");
jmethodID add = env->GetMethodID(listClass,"add","(Ljava/lang/Object;)Z");
if (dir_name.empty()) {
LOGE("dir_name is null !");
return;
}
DIR *dir = opendir(dir_name.c_str());
if (NULL == dir) {
LOGE("Can not open dir,Check path or permission!");
return;
}
dirent *file;
while ((file = readdir(dir)) != NULL) {
if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) {
// LOGE("ignore . and ..");
continue;
}
if (file->d_type == DT_DIR) {
string filePath = dir_name + "/" + file->d_name;
showAllFiles(env,job,filePath);
} else {
string filename = file->d_name;
int size = filename.size();
if(filename.size()>3){
string endName = filename.substr(size-4,size-1);
int flag = strcmp(endName.c_str(),".txt");
if(flag==0){
LOGE("filePath:%s/%s%d", dir_name.c_str(), file->d_name,index);
string filepath= dir_name+file->d_name;
index++;
jstring item = (env)->NewStringUTF(filepath.c_str());
env->CallBooleanMethod(obj,add,item);
}
}
}
}
closedir(dir);
if(i==1){
isFirst = true;
env->CallVoidMethod(job,showMid);
}
}
void findFilesByType(JNIEnv* env,jobject jclass,jstring path){
const char *pathName = env->GetStringUTFChars(path, NULL);
showAllFiles(env,jclass,pathName);
}
jint RegisterMainActivity(JNIEnv *env){
jclass clazz = env->FindClass("com/example/filemanager/MainActivity");
if(clazz == NULL){
return JNI_ERR;
}
JNINativeMethod methods_JNITest[] = {
{"gun", "()Ljava/lang/String;",(void*)gun},
{"findAllFileByType", "(Ljava/lang/String;)V",(void*)findFilesByType}
};
return env->RegisterNatives(clazz,methods_JNITest, sizeof(methods_JNITest)/ sizeof(methods_JNITest[0]));
}
jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = NULL;
if(vm->GetEnv((void **)&env,JNI_VERSION_1_6)!=JNI_OK){
return JNI_ERR;
}
jint result1 = RegisterMainActivity(env);
return JNI_VERSION_1_6;
}
}
3.主类代码如下:
package com.example.filemanager
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.yanzhenjie.permission.Action
import com.yanzhenjie.permission.AndPermission
import com.yanzhenjie.permission.runtime.Permission
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.view.*
import java.io.File
class MainActivity : AppCompatActivity() {
init {
System.loadLibrary("native-lib")
}
var startiem:Long = 0
var javaStarTime:Long = 0
var adapter:MyAdapter? = null
var isFirst = true
var files:ArrayList<String> = ArrayList<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
text.setText(gun())
AndPermission.with(this)
.runtime()
.permission(Permission.Group.STORAGE)
.onGranted(Action { permissions: List<String?>? ->
startiem = System.currentTimeMillis()
javaStarTime = startiem
findAllFileByType("/storage/emulated/0")
showJavaAllFiels("/storage/emulated/0")
})
.onDenied(Action { permissions: List<String?>? -> })
.start()
}
fun showFiles(){
Log.d("useTime","time:"+(System.currentTimeMillis()-startiem))
for((index ,item) in files.withIndex()){
Log.d("finish","finish:"+item+index)
}
adapter = MyAdapter(applicationContext,files)
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
}
fun showJavaAllFiels(path:String){
var i = 0
if(isFirst){
i=1
isFirst = false
}
var file: File = File(path)
if(file.exists()){
for(fileitm in file.listFiles()){
if (fileitm.isFile){
if(fileitm.name.endsWith(".txt"))
Log.d("javaFile","java:"+path+"/"+fileitm.name)
}else{
showJavaAllFiels(path+"/"+fileitm.name)
}
}
}else{
Log.e("native","file is not exit!")
}
if(i==1){
Log.d("useTime","java:"+(System.currentTimeMillis()-javaStarTime))
}
}
//native methods
external fun gun(): String
external fun findAllFileByType(path:String)
//class
class MyAdapter constructor(context: Context,arrayList: ArrayList<String>):
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private var context:Context? = null
private var arrayList:ArrayList<String>? =null
init{
this.context = context
this.arrayList = arrayList
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.recycler_item,parent,false)
return MyViewHolder(itemView)
}
override fun getItemCount(): Int {
return arrayList!!.size
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
var myViewHolder = holder as MyViewHolder
myViewHolder.textView!!.text = arrayList!!.get(position)
}
inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var textView:TextView? = null
init {
textView =itemView.findViewById<TextView>(R.id.textView)
}
}
}
}
4.性能对比如下:性能还是很快的,遍历全盘基本是1秒以内,而java就是慢如狗,最近打算做个人用的文件管理应用,市面上的实在是太垃圾了,真的,体验真的不好。
2021-03-31 23:31:55.059 24768-24768/com.example.filemanager D/useTime: time:987
2021-03-31 23:31:58.340 24768-24768/com.example.filemanager D/useTime: java:4268