项目实战:JNI-Java与C的交互(简单加密解密)
2016-08-18 20:10
447 查看
JNI,Java NativeInterface,它提供了若干的API实现了Java和其他语言的通信(主要是C&C++)。从Java1.1开始,JNI标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。
最好的学习手册就是官方原文档,链接奉上:
http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html(Java Native Interface SpecificationContents)
有了之前的“Hello World”基础后,现在开发就容易很多了。
先在.h中添加:
#include <stdio.h>
#include <String.h>
之后要用到,不然有的是坑等着你。
在.c文件中添加加密函数,源代码如下,看了就秒懂。
这里需要注意的是2个方法的使用,大大减小了开发工作量。
const char * GetStringUTFChars(JNIEnv *env, jstring string,
Returns a pointer to an array of bytes representing the string in modified UTF-8 encoding. This array is valid until it is released by
If
set to
no copy is made.
Constructs a new
详情可见开发手册。
底层工作到此结束。
回到上层。
在JniUtils中添加本地方法:
之后在MainActivity.java和xml布局文件中做相应修改,直接调用就ok啦。
MainActivity.java源代码奉上。
jniutils.c源代码奉上:
小贴士:
1.遇到类似error: '***'undeclared (first use in this function)的错误,
如果你按我说的做就不会遇到,错误原因是少了相应的头文件,添加即可。
2.遇到类似A/libc﹕ Fatalsignal 11 (SIGSEGV) at 0x00000000 (code=1), thread 25427 (pool-1-thread-2)的错误,
看上去很吓人,这个问题往往出在使用的so库里面。需要用ndk-stack工具来定位错误。
但一般也没那么复杂,凭着自己的C和JNI功底,调试源代码,重新编译即可解决。
最好的学习手册就是官方原文档,链接奉上:
http://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/jniTOC.html(Java Native Interface SpecificationContents)
有了之前的“Hello World”基础后,现在开发就容易很多了。
先在.h中添加:
#include <stdio.h>
#include <String.h>
之后要用到,不然有的是坑等着你。
在.c文件中添加加密函数,源代码如下,看了就秒懂。
JNIEXPORT jstring JNICALL Java_com_quan_car_qmeeting_JniUtils_encodeFromC (JNIEnv *env, jobject obj,jstring passWord,jint length){ //生成native的char指针 const char* c = (*env)->GetStringUTFChars(env,passWord,NULL); char* cStr = c; int i ; for(i = 0;i < length;i++){ *(cStr + i) += 1; } //将c语言字符串转化为java字符串 return (*env)->NewStringUTF(env, c); }
这里需要注意的是2个方法的使用,大大减小了开发工作量。
const char * GetStringUTFChars(JNIEnv *env, jstring string,
jboolean *isCopy);
Returns a pointer to an array of bytes representing the string in modified UTF-8 encoding. This array is valid until it is released by
ReleaseStringUTFChars().
If
isCopyis not
NULL, then
*isCopyis
set to
JNI_TRUEif a copy is made; or it is set to
JNI_FALSEif
no copy is made.
jstring NewStringUTF(JNIEnv *env, const char *bytes);
Constructs a new
java.lang.Stringobject from an array of characters in modified UTF-8 encoding.
详情可见开发手册。
底层工作到此结束。
回到上层。
在JniUtils中添加本地方法:
//加密本地方法 public static native String encodeFromC(String text, int length); //解密本地方法 public static native String decodeFromC(String text, int length);
之后在MainActivity.java和xml布局文件中做相应修改,直接调用就ok啦。
MainActivity.java源代码奉上。
import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText userName_et_main; private EditText passWord_et_main; private Button login_btn_main; private Button regist_btn_main; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); login_btn_main.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String userName = userName_et_main.getText().toString(); if(TextUtils.isEmpty(userName)){ Toast.makeText(getApplication(), "用户名不能为空!", Toast.LENGTH_SHORT).show(); } Log.d("权兴权意-userName:",userName); String passWord = passWord_et_main.getText().toString(); if(TextUtils.isEmpty(passWord)){ Toast.makeText(getApplication(), "密码不能为空!", Toast.LENGTH_SHORT).show(); } Log.d("权兴权意-passWord:",passWord); Log.d("encodeFromC(passWord):",JniUtils.encodeFromC(passWord,passWord.length())); String encodePassWord = JniUtils.encodeFromC(passWord,passWord.length()); Log.d("decodeFromC(passWord):",JniUtils.decodeFromC(encodePassWord,encodePassWord.length())); } }); regist_btn_main.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(); intent.setClass(MainActivity.this, RegistActivity.class); startActivity(intent); } }); } private void initView() { userName_et_main = (EditText) findViewById(R.id.userName_et_main); passWord_et_main = (EditText) findViewById(R.id.passWord_et_main); login_btn_main = (Button) findViewById(R.id.login_btn_main); regist_btn_main = (Button) findViewById(R.id.regist_btn_main); } }
jniutils.c源代码奉上:
// // Created by 权兴权意 on 2016/8/17. // #include "com_ndkjnidemo_quan_ndkjnidemo_JniUtils.h" /* * Class: Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils * Method: getStringFormC * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_getStringFormC (JNIEnv *env, jobject obj){ return (*env)->NewStringUTF(env, "权兴权意-这里是来自C的string"); } JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_updateString (JNIEnv *env, jobject obj,jstring js){ //jstring js //生成native的char指针 const char* c = (*env)->GetStringUTFChars(env,js,NULL); // if(c != NULL){ // LOGV("from Java const char*%s",c); // } // if(js != NULL){ // //LOGV("from Java jstring%s",js); // return (*env)->NewStringUTF(env, js); // } return (*env)->NewStringUTF(env, c); //return (*env)->NewStringUTF(env, "权兴权意-来自updateString"); } JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_encodeFromC (JNIEnv *env, jobject obj,jstring passWord,jint length){ //生成native的char指针 const char* c = (*env)->GetStringUTFChars(env,passWord,NULL); char* cStr = c; int i ; for(i = 0;i < length;i++){ *(cStr + i) += 1; } //将c语言字符串转化为java字符串 return (*env)->NewStringUTF(env, c); } JNIEXPORT jstring JNICALL Java_com_ndkjnidemo_quan_ndkjnidemo_JniUtils_decodeFromC (JNIEnv *env, jobject obj,jstring passWord,jint length){ //生成native的char指针 const char* c = (*env)->GetStringUTFChars(env,passWord,NULL); char* cStr = c; int i ; for(i = 0;i < length;i++){ *(cStr + i) -= 1; } return (*env)->NewStringUTF(env, c); }
小贴士:
1.遇到类似error: '***'undeclared (first use in this function)的错误,
如果你按我说的做就不会遇到,错误原因是少了相应的头文件,添加即可。
2.遇到类似A/libc﹕ Fatalsignal 11 (SIGSEGV) at 0x00000000 (code=1), thread 25427 (pool-1-thread-2)的错误,
看上去很吓人,这个问题往往出在使用的so库里面。需要用ndk-stack工具来定位错误。
但一般也没那么复杂,凭着自己的C和JNI功底,调试源代码,重新编译即可解决。
相关文章推荐
- RSA算法简单实现加密、解密、签名、验证(原创Java程序)
- java 加密解密简单实现
- java 加密解密简单实现
- C# Java间进行RSA加密解密交互 .
- C# Java间进行RSA加密解密交互(二)
- jsp,java中文乱码问题另类解决方案,jni加密、解密编码
- java加密解密(简单的小例子)
- java实现字符的简单加密和解密
- java 加密解密简单实现
- C# Java间进行RSA加密解密交互(二) .
- Java与.Net环境下RSA加密解密交互不成功的问题解决
- java和.net 交互加密解密
- (黑马)总结一:Java 加密解密简单例子
- C# Java间进行RSA加密解密交互
- Java - 简单加密-解密方法包装, 含encode(),decode(),md5()
- java的简单加密/解密方法
- java 加密解密简单实现
- java 加密解密简单实现
- C# Java间进行RSA加密解密交互(三)
- java 加密解密简单实现