ndk 实现 登录的功能(java 和 C 的调用)

配置ndk 的环境, 参考网址:    http://blog.csdn.net/xiuxiu_861223/article/details/78792939


实际代码:

页面:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="bw.com.day15.MainActivity">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入用户名"
        android:id="@+id/name_et_id"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入密码"
        android:id="@+id/pwd_et_id"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入验证码 1234"
        android:id="@+id/code_et_id"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="登录"
        android:onClick="login"
        />

</LinearLayout>

代码:

  1, 创建 JinTest.java

public class JniTest {

    private static Context context;

    public JniTest(Context context)
    {
        this.context = context;
    }

    //通过静态代码块 , 引入so 文件
    static {
        System.loadLibrary("app");
    }

    public static String codeError = "验证码错误";
    public static String userNameError = "用户名错误";
    public static String loginSuccess = "登录成功";

    public static int count = 10;

    // native 修饰的方法
    public static native  String getStr();
    public static native  int  getCount();

    
    //登录的功能:  用户名, 密码, 验证码
    public static native   String login(String uName,String uPwd,int uCode);
    /**
     * 用C 访问java 显示登录信息
     *
javah -d jni -classpath ../../build/intermediates/classes/debug bw.com.day15.JniTest
     */
    public static void showMessage(String message)
    {
        Toast.makeText(context,message, Toast.LENGTH_SHORT).show();
    }
}

2,  点击菜单栏的Make Module 'app'即可


3, 生成头文件(*.h

    首先打开工具栏的Terminal工具,使用cd命令定位到Moduel appmain目录

    执行:  红色的文字是需要根据自己的Jni 改变的

javah -d jni -classpath ../../build/intermediates/classes/debug bw.com.day15.JniTest

4, 创建  :bw_com_day15_JniTest.c

 

#include "bw_com_day15_JniTest.h"

JNIEXPORT jstring JNICALL Java_bw_com_day15_JniTest_login
  (JNIEnv *env, jclass jobj, jstring juName, jstring juPwd, jint jcode)
  {
         const char* resultMessage;//声明字符变量
        jclass jc;

        //1, 加载java 类中的class 对象
        jc = (*env)->FindClass(env, "bw/com/day15/JniTest");//反射机制来获取对象
        //jc = (*env)->GetObjectClass(env, jobj);//使用GetObjectClass函数来获取class对象:

        //2, 获取java 类的成员变量
        //2.1 获取java 类成员变量的id
       jfieldID errorCodeID = (*env)->GetStaticFieldID(env,jc,"codeError","Ljava/lang/String;");
       jfieldID userNameErrorID = (*env)->GetStaticFieldID(env,jc,"userNameError","Ljava/lang/String;");
       jfieldID loginSuccessID = (*env)->GetStaticFieldID(env,jc,"loginSuccess","Ljava/lang/String;");


        //2.2 通过成员变量id , 获取java 类成员变量
       jstring jerrorCode= (*env)->GetStaticObjectField(env,jc,errorCodeID);
        jstring juserNameError= (*env)->GetStaticObjectField(env,jc,userNameErrorID);
       jstring jloginSuccess = (*env)->GetStaticObjectField(env,jc,loginSuccessID);

       //3, 获取java 类的方法
       //3.1 获取java 类的方法
       jmethodID showMessage = (*env)->GetStaticMethodID(env,jc,"showMessage","(Ljava/lang/String;)V");
       //查看验证码是否正确
       if(jcode==1234)
       {
            const char* cstr;
            jboolean isCopy;

            cstr = (*env)->GetStringUTFChars(env,juName,&isCopy);
            int result = strcmp(cstr,"admin");
            if(result==0)
            {
                resultMessage = "login success";
               // 3.2  通过方法的id , 回调java 的代码
              (*env)->CallStaticVoidMethod(env,jc,showMessage,jloginSuccess);

            }else
            {
                 resultMessage = "login Error";
               // 3.2  通过方法的id , 回调java 的代码
              (*env)->CallStaticVoidMethod(env,jc,showMessage,juserNameError);
            }
       }
       else
       {
            resultMessage = "code Error";
          // 3.2  通过方法的id , 回调java 的代码
         (*env)->CallStaticVoidMethod(env,jc,showMessage,jerrorCode);
       }

     return  jloginSuccess;
  }

// 返回int 类型的变量
  JNIEXPORT jint JNICALL Java_bw_com_day15_JniTest_getCount
    (JNIEnv *env, jclass jobj)
    {
    jclass jc;

            //1, 加载java 类中的class 对象
            jc = (*env)->FindClass(env, "bw/com/day15/JniTest");//反射机制来获取对象
            //jc = (*env)->GetObjectClass(env, jobj);//使用GetObjectClass函数来获取class对象:

            //得到int 类型的变量
           jfieldID  fid = (*env)->GetStaticFieldID(env, jc, "count", "I");

            // 3.获取静态变量num的值
            jint  num = (*env)->GetStaticIntField(env,jc,fid);

           return num;
    }

5, 准备就绪,开始构建.so文件  -- 点击菜单栏的Make Module 'app'即可


6, 

使用so库。在JniTest.java中添加代码

static {    

System.loadLibrary("app"); 

}


7, MainActivity.java

public class MainActivity extends AppCompatActivity {

    private EditText nameEt;
    private EditText pwdEt;
    private EditText codeEt;

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

        nameEt = (EditText) findViewById(R.id.name_et_id);
        pwdEt = (EditText) findViewById(R.id.pwd_et_id);
        codeEt = (EditText) findViewById(R.id.code_et_id);

    }

    public void login(View view) {

        JniTest jniTest = new JniTest(this);

        int code =Integer.parseInt(codeEt.getText().toString());//String--> int
        String str = jniTest.login(nameEt.getText().toString(),pwdEt.getText().toString(),code);

        int count = JniTest.getCount();

        //Toast.makeText(this, str + "----->"+count, Toast.LENGTH_SHORT).show();
    }
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android NDK中,我们可以使用JNI(Java Native Interface)来实现C/C++代码和Java代码的相互调用。 下面是一个简单的例子,展示了如何在NDK调用Java层的方法。 首先,在Java层中创建一个类,并在其中声明一个需要被C/C++回调的方法: ```java public class MyCallback { public void processData(byte[] data) { // 处理数据的逻辑 } } ``` 然后,在C/C++代码中,我们需要使用JNI来获取Java层的MyCallback对象,并调用其processData方法。具体步骤如下: 1. 首先,需要在C/C++代码中引入JNI头文件: ```c++ #include <jni.h> ``` 2. 获取Java层的MyCallback对象: ```c++ JNIEnv* env; JavaVM* jvm; // 获取当前线程的JNIEnv指针 jvm->AttachCurrentThread(&env, NULL); // 获取MyCallback类 jclass myCallbackClass = env->FindClass("com/example/MyCallback"); // 获取MyCallback对象 jmethodID constructor = env->GetMethodID(myCallbackClass, "<init>", "()V"); jobject myCallbackObj = env->NewObject(myCallbackClass, constructor); ``` 3. 调用MyCallback对象的processData方法: ```c++ // 获取processData方法的ID jmethodID processDataMethod = env->GetMethodID(myCallbackClass, "processData", "([B)V"); // 构造byte[]对象 jbyteArray data = env->NewByteArray(size); env->SetByteArrayRegion(data, 0, size, (jbyte*)buf); // 调用processData方法 env->CallVoidMethod(myCallbackObj, processDataMethod, data); ``` 最后,记得在C/C++代码中释放JNI相关资源: ```c++ jvm->DetachCurrentThread(); env->DeleteLocalRef(myCallbackClass); env->DeleteLocalRef(myCallbackObj); env->DeleteLocalRef(data); ``` 以上就是在NDK实现线程回调Java层方法的基本步骤。需要注意的是,在调用Java层方法时,需要使用JNIEnv指针。此外,如果在多线程环境下操作JNI,需要使用jvm->AttachCurrentThread()方法获取当前线程的JNIEnv指针。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值