Android Studio NDK 学习之接受Java传入的字符串

本博客是基于Android Studio 1.3 preview版本,且默认你已经安装了Android SDK, Android NDK。

用Android Studio新建一个工程叫Prompt,其目录结构如下:

├── Prompt.iml

├── app

│   ├── app.iml

│   ├── build

│   ├── build.gradle

│   ├── libs

│   ├── proguard-rules.pro

│   └── src

├── build

│   └── intermediates

├── build.gradle

├── gradle

│   └── wrapper

├── gradle.properties

├── gradlew

├── gradlew.bat

├── local.properties

└── settings.gradle

切换到android视图,可见如下目录:

第一步,编写JNI代码:

1、新建jni文件夹,在jni文件夹下创建logger.h,用来打印输出日志的,其内容如下:

#ifndef PROMPT_LOGGER_H_H
#define PROMPT_LOGGER_H_H

#include <jni.h>
#include <android/log.h>

/**
 * 定义log标签
 */
#define TAG "jni_logger"

/**
 * 定义info信息
 */
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)

/**
 * 定义debug信息
 */
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

/**
 * 定义error信息
 */
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)

#endif //PROMPT_LOGGER_H_H

2、接着创建prompt_jni.c主要用来注册绑定java函数和native函数,以及java函数在c中相应函数的具体实现, 内容如下:

#include "logger.h"

#ifndef NULL
#define NULL ((void *) 0)
#endif

/**
 * 获取数组的大小
 */
#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))

#define JNIREG_CLASS "com/ndk/clarck/prompt/MainActivity"

/**
 * 返回字符串
 */
JNIEXPORT jstring JNICALL native_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
    char outbuf[128];
    int len = (*env)->GetStringLength(env, prompt);
    (*env)->GetStringUTFRegion(env, prompt, 0, len, outbuf);

    return (*env)->NewStringUTF(env, outbuf);
}

/**
 * Java和JNI函数绑定
 */
static JNINativeMethod method_table[] = {
        {"getLine", "(Ljava/lang/String;)Ljava/lang/String;", (void*)native_getLine},
};

/**
 * 注册native方法到java中
 */
static int registerNativeMethods(JNIEnv *env, const char* className,
            JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL) {
        return JNI_FALSE;
    }

    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
    {
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

/**
 * 调用注册方法
 */
int register_ndk_load(JNIEnv *env)
{
    return registerNativeMethods(env, JNIREG_CLASS, method_table, NELEM(method_table));
}

JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
        return result;
    }

    register_ndk_load(env);
    return JNI_VERSION_1_4;
}

3、java层调用如下:

package com.ndk.clarck.prompt;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        String getLine = getLine("Type a line:");
        Log.d("Test", "getLine: " + getLine);
    }

    public native String getLine(String prompt);

    static {
        System.loadLibrary("prompt_jni");
    }
}

第二步,配置如下环境,执行编译命令:

1、在local.properties配置SDK和NDK路径如下:

 sdk.dir=xxxx

 ndk.dir=xxx

2、打开gradle-wrapper.properties,将其配置修改为使用Gradle 2.5来编译(详情参考:http://www.cnblogs.com/tanlon/p/4731283.html):

#Mon Aug 17 20:34:50 HKT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip

3、配置Project下面的build.gradle,其内容如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath ‘com.android.tools.build:gradle-experimental:0.2.0‘

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

4、配置Module下面的build.gradle,其内容如下:

apply plugin: ‘com.android.model.application‘

model {
    android {
        compileSdkVersion = 21
        buildToolsVersion = "22.0.1"

        defaultConfig.with {
            applicationId = "com.ndk.clarck.prompt"
            minSdkVersion.apiLevel    = 15
            targetSdkVersion.apiLevel = 21
        }
    }

    android.ndk {
        moduleName = "prompt_jni"
        ldLibs    += ["log"]
    }

    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles  += file(‘proguard-rules.pro‘)
        }
    }

    android.productFlavors {
        create ("arm7") {
            ndk.abiFilters += "armeabi-v7a"
        }
        create ("arm8") {
            ndk.abiFilters += "arm64-v8a"
        }
        create ("x86-32") {
            ndk.abiFilters += "x86"
        }
        // for detailed abiFilter descriptions, refer to "Supported ABIs" @
        // https://developer.android.com/ndk/guides/abis.html#sa

        // build one including all cpu architectures
        create("all")
    }
}

5、执行Build->Make Project,得到如下输出:

1:27:09 PM Executing tasks: [:app:compileAllDebugSources, :app:compileAllDebugAndroidTestSources]
1:27:10 PM Gradle build finished in 779ms

6、执行Run,即可运行项目了。

经验:

1、遇到Gradle sync failed: Cause: org.gradle.api.internal.ExtensibleDynamicObject这种错误的解决办法:

  将Module下的build.gradle所有编译参数赋值都是采用xxx = xxx这种方式,而不能采用 xxx xxx这种赋值的方式

2、Android Studio Gradle编译确实比Eclipse中采用Android Makefile要方便很多。

时间: 2024-11-01 17:24:26

Android Studio NDK 学习之接受Java传入的字符串的相关文章

Android Studio NDK 学习之接受Java传入的Int数组

本博客是基于Android Studio 1.3 preview版本,且默认你已经安装了Android SDK, Android NDK. 用Android Studio新建一个工程叫AndroidJNI_IntArray,其目录结构如下: ├── AndroidJNI_IntArray.iml ├── app │   ├── app.iml │   ├── build │   ├── build.gradle │   ├── libs │   ├── proguard-rules.pro │ 

Android Studio NDK开发-JNI调用Java方法

相对于NDK来说SDK里面有更多API可以调用,有时候我们在做NDK开发的时候,需要在JNI直接Java中的方法和变量,比如callback,系统信息等.... 如何在JNI中调用Java方法呢?就需要先了解FindClass和GetMethodID了. FindClass和GetMethodID 在JNI中可以通过FindClass可以找到Java类,得到jclass,例如: jclass clz=(*env)->FindClass(env,"com/jjz/JniHandle"

android studio NDK 开发初探

android studio NDK 开发初探 环境配置 1)下载ndk 2)在android studio中配置ndk 路径 3)配置gradle 在gradle.properties中加入 android.useDeprecatedNdk=true配置 开启ndk 在开发过程中我们有时还会用到c++中到stl库这时我们就需要在build.gradle 中加入 defaultConfig { ndk { moduleName "jnitest" stl "stlport_s

Android Studio NDK开发

整理完Eclipse的NDK开发,再整理下Android Studio的.. 一个比较不错的百度网盘: http://pan.baidu.com/share/home?uk=2383159761  经常更新最新的Android方面的开发包,可以到里面下载到ndk的包 创建一个Android的工程,放一个TextView用于显示文字,功能很简单,从native层获取字符串并显示到TextView上 然后编写相关代码: public class MainActivity extends AppCom

android的ndk学习(1)

android的ndk学习(1) 之前学了一段时间ndk,总觉得要总结一下.ndk使得非常方便地实现java和C与C++代码的相互沟通,合理地掌握使用ndk可以提高应用程序的执行效率,所以对于学习anndroid开发的人来说,ndk是必须掌握的工具.刚刚开始学习的时候是有点兴奋,有点害怕的,兴奋是因为之前学过C++语言,能将学过的东西结合在一起,感觉可以做出更好的东西,害怕的是之前听身边的大神说ndk在android开发中是非常难的内容之一.但是不管怎么说我还是找了本书,看了视频,找了一些电子资

Android Studio NDK及so文件开发

前言 什么是NDK? NDK全称是Native Development Kit,NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk.NDK集成了交叉编译器(交叉编译器需要UNIX或LINUX系统环境),并提供了相应的mk文件隔离CPU.平台.ABI等差异,开发人员只需要简单修改mk文件(指出"哪些文件需要编译"."编译特性要求"等),就可以创建出so. 为什么使用NDK? 1.代码的保护.由于apk的ja

[Android Studio][NDK]Execution failed for task &#39;:app:compileDebugNdk&#39;. Error Code:2

Execution failed for task ':app:compileDebugNdk'. > com.android.ide.common.internal.LoggedErrorException: Failed to run command: C:\Users\sodinochen\AppData\Local\Android\ndk-r10b\ndk-build.cmd NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=C:\Users\sodinoch

JAVA传入一个字符串,返回一个字符串中的大写字母

/** * * @param 传入一个字符串 * @return 返回一个字符串中的大写字母 */ private static String stringChange(String s) { if (Utils.isStrEmpty(s)) return ""; StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { if (Character.isUpperCase(s.ch

java传入一个字符串 将它分割成大写字符为首的字符串数组

/* * 传入一个字符串 将它分割成大写字符为首的字符串数组 */ private ArrayList<String> splitByUpperCase(String str) { ArrayList<String> rs = new ArrayList<String>(); int index = 0; int len = str.length(); for (int i = 1; i < len; i++) { if (Character.isUpperCas