安卓开发学习之ndk实现文件的加密解密

背景

这几天在学习Android开发里的ndk开发,今天拿文件的加密解密做为练习。

功能很简单,俩按钮,一个加密一个解密,加密方式就是拿文件的字符跟密钥进行异或,解密方式也是异或


native层

首先动态注册,把java的native方法跟c函数绑定,详情参见文章安卓开发学习之ndk动态注册

以加密为例,我对应的c函数是fileEncrypt(),完整代码如下

jstring fileEncrypt(JNIEnv *env, jclass type, jstring filePath) {
    __android_log_print(ANDROID_LOG_INFO, "native", "进入加密过程");
    fileIndex = 1;

    const char *path = (*env).GetStringUTFChars(filePath, JNI_FALSE);
    const char *newPath = getNewName(path);

    __android_log_print(ANDROID_LOG_INFO, "native", "new file path:%s", newPath);

    FILE *frp = fopen(path, "rb");
    FILE *fwp = fopen(newPath, "wb");

    if (frp == NULL) {
        __android_log_print(ANDROID_LOG_INFO, "native", "%s:此文件不存在或没有读权限", path);
        return NULL;
    }

    if (fwp == NULL) {
        __android_log_print(ANDROID_LOG_INFO, "native", "%s:没有写权限", newPath);
        return NULL;
    }

    int buf;
    int i = 0;

    while ((buf = fgetc(frp)) != EOF) {
        fputc(buf ^ key[i % keyLen], fwp);
        i++;
    }

    fclose(frp);
    fclose(fwp);
    free((void *) path);

    __android_log_print(ANDROID_LOG_INFO, "native", "文件加密结束");
    return env->NewStringUTF(newPath);
}

调用了getName()方法设定新文件的名字,代码如下

char *getNewName(const char *oldName) {
    int len = strlen(oldName);
    char *newName = new char[len + 1];
    int i = 0;

    for (; i < len && oldName[i] != '.'; ++i) {
        newName[i] = oldName[i];
    }

    newName[i] = '1' + fileIndex;
    fileIndex++;

    for (; i < len; ++i) {
        newName[i+1] = oldName[i];
    }

    return newName;
}

而后涉及的密钥信息如下

const char *key = "101010101";
int keyLen = strlen(key);
int fileIndex = 1;

可以看到,所谓的加密就是跟复制粘贴一样的流程化代码,无需赘言


java层

首先在清单文件里声明写外存权限

而后由于Android6.0以后要动态申请权限,所以还要在MainActivity里进行相关操作,代码如下:

public class MainActivity extends Activity {
    public static final String TAG = "MainActivity";
    private Button btn_encrypt, btn_decrypt;
    private String filePath = Environment.getExternalStorageDirectory() + "/new.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_encrypt = (Button)findViewById(R.id.btn_encrypt);
        btn_decrypt = (Button)findViewById(R.id.btn_decrypt);

        btn_encrypt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "待加密文件路径:"+filePath);
                if (!TextUtils.isEmpty(filePath) && new File(filePath).exists()) {
                    filePath = FileUtil.fileEncrypt(filePath);
                }
            }
        });

        btn_decrypt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i(TAG, "待解密文件路径:"+filePath);
                if (!TextUtils.isEmpty(filePath) && new File(filePath).exists()) {
                    filePath = FileUtil.fileDecrypt(filePath);
                }
            }
        });

        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
            btn_decrypt.setClickable(false);
            btn_encrypt.setClickable(false);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == 0) {
            if (checkSelfPermission(permissions[0]) == PackageManager.PERMISSION_GRANTED) {
                btn_decrypt.setClickable(true);
                btn_encrypt.setClickable(true);
            }
        }
    }
}

调用的FileUtil类的代码如下

public class FileUtil {
    static {
        System.loadLibrary("native-lib");
    }

    public static native String fileEncrypt(String filePath);
    public static native String fileDecrypt(String filePath);
}

代码很简单,只是做一下记录


结语和代码地址

网上还有文件的分割和合并的案例,其实本质也是文件的IO,所以此处略过

代码地址:

https://github.com/songzeceng/first/tree/file_encrypt_decrypt

猜你喜欢

转载自blog.csdn.net/qq_37475168/article/details/80405685