欧雨鹏 发表于 2020-10-23 01:32

折腾折腾用android studio去编写so--动态注册

本帖最后由 欧雨鹏 于 2020-10-23 22:02 编辑

静态注册C方法:https://www.52pojie.cn/thread-1288308-1-1.html


序言

因为android studio版本我给升级到4.1。有些以前的操作可能无法进行完整的操作。
之前在搜索资料的时候,看到一位前辈提到,除了cmake,还可以ndk-build。
现在重新进行一次操作。动态注册c/c++,代码量比静态注册C比较多。


分两步过程 :先把代码码一遍。再一次性生成操作。

一、创建jni类,生成h和实现native,绑定注册
1.创建jni类,添加native方法
在src/main/java/com.example.myapplication里面创建 java类,操作:选中com.example.myapplication,右键,New---Java Class.
这里取的类名为:lstnjisuan

添加native方法,为loadLibrary设置名称

代码如下:
package com.example.myapplication;

public class lstnjisuan {
      static{
            System.loadLibrary("funjisuan");//设置so名称
      }

    public native float add(float firstnumber,float secondnumber);//加法方法
    public native float sub(float firstnumber,float secondnumber);//减法方法
    public native float mul(float firstnumber,float secondnumber);//剩法方法
    public native float div(float firstnumber,float secondnumber);//除法方法
}

然后先把MainActivity里的调用方法写完,后面就不会再来写了。
先给界面拖几个控件,设置 一下id
控件为:2个 plain text,4个button,1个textview
用于输入的两个plain text ,id分别为:numbertext1,numbertext2
5个button 用于选 择加减乘除,计算按钮,id分别为addbutton,subbutton,mulbutton,divbutton
1个textview控件用于显示结果,id为:sumtextview
因为懒得搞布局,把辅助线添加,拉一拉界线。免得运行控件全跑了。(惨痛的教训)



这样,控件就设置完成了,界面也算做好了。
下面开始写代码,在MainActivity类里进行初始化和计算操作
先对控件做一个初始化.

代码如下:
package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    private Button add;//这五个按钮用于获取id和进行监听
    private Button sub;
    private Button mul;
    private Button div;
    private EditText first;//用来获取输入两个操作数
    private EditText second;
    private TextView result;//用来转换后输出到textview显示结果的变量


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

    privatevoid contextinIt()
    {
      first=findViewById(R.id.numbertext1);
      second=findViewById(R.id.numbertext2);
      add=(Button) findViewById(R.id.addbutton);
      sub=(Button) findViewById(R.id.subbutton);
      mul=(Button) findViewById(R.id.mulbutton);
      div=(Button) findViewById(R.id.divbutton);
      result=findViewById(R.id.sumtextview);
    }
}
findViewById这个函数有什么 作用?
定位函数,主要是引用.R文件里的引用名。一般在R.java文件里系统会自动帮你给出你在XML里定义的ID或者Layout里面的名称。


接着设置button监听计算.
完整代码如下:
package com.example.myapplication9;

import androidx.appcompat.app.AppCompatActivity;
import android.view.View.OnClickListener;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private Button add;//这四个按钮用于获取id和进行监听
    private Button sub;
    private Button mul;
    private Button div;
    private EditText first;//用来获取输入两个操作数
    private EditText second;
    private TextView result;
    private float oneNumber;//临时变量,用于计算和获取结果
    private float twoNumber;
    private float resultsum=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      controlinIt();
      add.setOnClickListener(onls);
      sub.setOnClickListener(onls);
      mul.setOnClickListener(onls);
      div.setOnClickListener(onls);

    }
    private void controlinIt()
    {
      first=findViewById(R.id.numbertext1);
      second=findViewById(R.id.numbertext2);
      add=(Button) findViewById(R.id.addbutton);
      sub=(Button) findViewById(R.id.subbutton);
      mul=(Button) findViewById(R.id.mulbutton);
      div=(Button) findViewById(R.id.divbutton);
      result=(TextView)findViewById(R.id.sumtextview);
    }



      privateOnClickListener onls=new OnClickListener()
      {
            public void onClick(View v)
            {
                lstnjisuan ls=new lstnjisuan();
                switch (v.getId())
                {
                  case R.id.addbutton:
                        oneNumber=Float.parseFloat(first.getText().toString());
                        twoNumber=Float.parseFloat(second.getText().toString());
                        resultsum=ls.add(oneNumber,twoNumber);
                        result.setText(Float.toString(resultsum));
                        break;
                  case R.id.subbutton:
                        oneNumber=Float.parseFloat(first.getText().toString());
                        twoNumber=Float.parseFloat(second.getText().toString());
                        resultsum=ls.sub(oneNumber,twoNumber);
                        result.setText(Float.toString(resultsum));
                        break;
                  case R.id.mulbutton:
                        oneNumber=Float.parseFloat(first.getText().toString());
                        twoNumber=Float.parseFloat(second.getText().toString());
                        resultsum=ls.mul(oneNumber,twoNumber);
                        result.setText(Float.toString(resultsum));
                        break;
                  case R.id.divbutton:
                        oneNumber=Float.parseFloat(first.getText().toString());
                        twoNumber=Float.parseFloat(second.getText().toString());
                        resultsum=ls.div(oneNumber,twoNumber);
                        result.setText(Float.toString(resultsum));
                        break;
                  default:
                        break;
                }
            }
      };

    }





2.生成h文 件,并创建 c文 件实现,注册和绑定native方法

在main层,创建 一个jni文 件夹,操作:New---Folder---JNI Folder
alt+f12打开terminal,cd 到java层


执行javah命令
javah -d ../jni com.example.myapplication.lstnjisuan

生成h文件。


创建c文件,实现计算,注册和绑定
选中jni文件夹,右键,New---C/C++ Source File,选择文件格式为.c
这里设置名称为:bindNativeJisuan
实现代码如下:
//
// Created by pady on 2020/10/22.
//

#include "com_example_myapplication_lstnjisuan.h"


JNIEXPORT jfloat JNICALL Java_com_example_myapplication_lstnjisuan_add
(JNIEnv *env, jobject obj, jfloat one, jfloat two)
{
    return one+two;
}


JNIEXPORT jfloat JNICALL Java_com_example_myapplication_lstnjisuan_sub
(JNIEnv *env, jobject obj, jfloat one, jfloat two)
{
    return one-two;
}


JNIEXPORT jfloat JNICALL Java_com_example_myapplication_lstnjisuan_mul
(JNIEnv *env, jobject obj, jfloat one, jfloat two)
{
    return one*two;
}


JNIEXPORT jfloat JNICALL Java_com_example_myapplication_lstnjisuan_div
(JNIEnv *env, jobject obj, jfloat one, jfloat two)
{
    return one/two;
}

//绑定java层中native方法
static const JNINativeMethod nativeMethod[]={
{"add","(FF)F",(void**)&Java_com_example_myapplication_lstnjisuan_add},
{"sub","(FF)F",(void**)&Java_com_example_myapplication_lstnjisuan_sub},
{"mul","(FF)F",(void**)&Java_com_example_myapplication_lstnjisuan_mul},
{"div","(FF)F",(void**)&Java_com_example_myapplication_lstnjisuan_div}
};

//注册nativeMethod方法,注册相应的类以及方法
jint registNativeMethod(JNIEnv *env)
{
    char* strname="com/example/myapplication9/lstnjisuan";
    jclass funclass=(*env)->FindClass(env,"strname");
    //进行JAVA层注册,如果不等于0返回错误

    if(((*env)-> RegisterNatives(env, funclass,nativeMethod,sizeof(nativeMethod)/sizeof(nativeMethod)))!=0)
    {
      return JNI_ERR;
    }
    return JNI_OK;
}

//实现JNI_ONLOAD动态注册
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm,void *reserved)
{
    JNIEnv *env;
    #ifndef JNI_VERSION_1_4
    if((*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_4)!=JNI_OK)
   {
            return JNI_ERR;
   }
    if(registNativeMethod(env)!=JNI_OK)
   {
            return JNI_ERR;
   }
   return JNI_VERSION_1_4;
    #endif

    if((*jvm)->GetEnv(jvm,(void**)&env,JNI_VERSION_1_6)!=JNI_OK)
    {
      return JNI_ERR;
    }
    if(registNativeMethod(env)!=JNI_OK)
    {
      return JNI_ERR;
    }
    return JNI_VERSION_1_6;

}


讲解:
JNINativeMethod 这是个结构体,在jni.h中定义。结构体如下:/*
* used in RegisterNatives to describe native method name, signature,
* and function pointer.
*/

typedef struct {
    char *name;
    char *signature;
    void *fnPtr;
} JNINativeMethod;上面有提到的,三个参数,name是java类中的native方法名,第二个参数是签名,就是指参数和返回值,最后是对应C函数的地址比如上面看到的"(FF)F",F是什么呢?是Smali语法的数据类型,F是float类型。括号里面两个FF,指明有两个float参数,外面的F,指明返回值是float.其它数据类型请查看smali语法。jint是什么?就是int类型。请看jni.h文件就明白了。上面很多函数都可以在jni.h文件中查看声明定义。可在jdk版本的include文件夹里找到jni.h文件。
上面除了计算实现的函数,其它的一列系操作最后就是主要被jni_onload函数调用的。代码都写好了。现在开始生成so文件。
============================================================================================================================================================================================================================

二、用ndk-build生成so操作(这一部分可不看,是旧版的操作,因为操作没有成功。采用CMake,请直接往下拉到第三部分看正常生成的操作。。)
这一段是不成功的操作,生成配置写在.mk文件里。折腾了一天都没成功。不知道是什么原因。1.在jni文件夹里,创建两个文件:android.mk和application.mk操作:New---File,直接输入android.mk .再次New---File,直接输入application.mk选中android.mk,输入以下内容LOCAL_PATH:=$(call my-dir)#开头必须定义的LOCAL_PATH,my-dir是宏函数,用来返回android.mk所在目录的路径
include $(CLEAR_VARS)#负责清除LOCAL_ 变量,除了path
LOCAL_MODULE:=funjisuan#模块名称,就是生成so的名称,和loadlibrary设置的名称一致
LOCAL_SRC_FILES:=Cfunjisuan.c#C源文件
include $(BUILD_SHARED_LIBRARY) #设置动态链接
application.mk内容如下:APP_ABI      :=all
APP_PLATFORM:=android-16
生成支持的所有版本如下图:
在terminal里cd 到jni层,就可以直接ndk-build了。操作方法:ndk-build
出现一个警告:Android NDK: WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 in E:/DownLoad/MyApplication8/app/src/main/AndroidManifest.xml. NDK binaries will *not* be compatible with de
vices older than android-16. See https://android.googlesource.com/platform/ndk/+/master/docs/user/common_problems.md for more information.
不添加就提示默认为android-16,添加了又给出这个警告。不知道怎么解决。so文件顺利生成。顺便查看了一下AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:roundIcon="@mipmap/ic_launcher_round"
      android:supportsRtl="true"
      android:theme="@style/Theme.MyApplication">
      <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
      </activity>
    </application>

</manifest>搜索WARNING: APP_PLATFORM android-16 is higher than android:minSdkVersion 1 ,大多说要把build/core/add-application.mk中的__ndk-warning改成__ndk_info改了依然警告.不管它了。查看生成的情况。发现在main层生成libs和obj
最后一步,直接Rebuild Project。这一步操作是成功的。查看一下生成的APK.so文件没有打包进去,也就是lib文件生成的各个版本的so没有打包进去。这种APK安装后是无法运行的。因为加载不到so文件。需要在build.gradle中设置ndkbuild?那么在build.gradle设置一下:在defaultConfig 节点里面添加下面代码: externalNativeBuild{
            ndkBuild{
                arguments "NDK_APPLICATION_MK:=src/main/jni/application.mk"
                cFlags "-DTEST_C_FLAGS1","-DTEST_C_FLAG2"
                cppFlags "-DTEST_CPP_FLAGS1","-DTEST_CPP_FLAG2"

            }
      }
在andoird节点添加下面代码: externalNativeBuild {
      ndkBuild {
            path file('src/main/jni/android.mk')
      }
    }
完整代码如下:plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
      applicationId "com.example.myapplication"
      minSdkVersion 22
      targetSdkVersion 30
      versionCode 1
      versionName "1.0"

      testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

      externalNativeBuild{
            ndkBuild{
                arguments "NDK_APPLICATION_MK:=src/main/jni/application.mk"
                cFlags "-DTEST_C_FLAGS1","-DTEST_C_FLAG2"
                cppFlags "-DTEST_CPP_FLAGS1","-DTEST_CPP_FLAG2"

            }
      }



    }

    buildTypes {
      release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
      }
    }
    compileOptions {
      sourceCompatibility JavaVersion.VERSION_1_8
      targetCompatibility JavaVersion.VERSION_1_8
    }

    externalNativeBuild {
      ndkBuild {
            path file('src/main/jni/android.mk')
      }
    }

}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
再次执行ReBuild Project又出现报错
D:/SDK/ndk/21.1.6352462/build//../build/core/build-module.mk:34: *** Android NDK:Assertion failure: LOCAL_MAKEFILE is not defined    .Stop.
executing external native build for ndkBuild E:\DownLoad\MyApplication8\app\src\main\jni\android.mk提示LOCAL_MAKEFILE is not defined。什么玩意?这个LOCAL_MAKEFILE是什么?找到build/core/build-module.mk,打开一看。#

$(call check-defined-LOCAL_MODULE,$(LOCAL_BUILD_SCRIPT))
$(call check-LOCAL_MODULE,$(LOCAL_MAKEFILE))

# This file is used to record the LOCAL_XXX definitions of a given
# module. It is included by BUILD_STATIC_LIBRARY, BUILD_SHARED_LIBRARY
# and others.
#
LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
ifndef LOCAL_MODULE_CLASS
$(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_MODULE_CLASS definition is missing !)
$(call __ndk_error,Aborting)
endif

$(if $(call module-class-check,$(LOCAL_MODULE_CLASS)),,\
$(call __ndk_info,$(LOCAL_MAKEFILE):$(LOCAL_MODULE): Unknown LOCAL_MODULE_CLASS value: $(LOCAL_MODULE_CLASS))\
$(call __ndk_error,Aborting)\
)

$(call module-add,$(LOCAL_MODULE))

# Eval sucks. It's not possible to preserve even properly escaped # characters
# as far as I can tell, and we need that for -Werror=#warnings. Manually stash
# all the flags variations so we can preserve these.
__ndk_modules.$(LOCAL_MODULE).ASFLAGS := $(LOCAL_ASFLAGS)
__ndk_modules.$(LOCAL_MODULE).ASMFLAGS := $(LOCAL_ASMFLAGS)
__ndk_modules.$(LOCAL_MODULE).CFLAGS := $(LOCAL_CFLAGS)
__ndk_modules.$(LOCAL_MODULE).CLANG_TIDY_FLAGS := $(LOCAL_CLANG_TIDY_FLAGS)
__ndk_modules.$(LOCAL_MODULE).CONLYFLAGS := $(LOCAL_CONLYFLAGS)
__ndk_modules.$(LOCAL_MODULE).CPPFLAGS := $(LOCAL_CPPFLAGS)
__ndk_modules.$(LOCAL_MODULE).CXXFLAGS := $(LOCAL_CXXFLAGS)
__ndk_modules.$(LOCAL_MODULE).LDFLAGS := $(LOCAL_LDFLAGS)
__ndk_modules.$(LOCAL_MODULE).RENDERSCRIPT_FLAGS := $(LOCAL_RENDERSCRIPT_FLAGS)
于是折腾了很久,最后android.mk改成这样。LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS:=optional
LOCAL_MODULE:=funjisuan
LOCAL_SRC_FILES:=bindNativeJisuan.c
LOCAL_MODULE_CLASS:=SHARED_LIBRAYIES
include $(BUILD_SHARED_LIBRARY)重新ndk-build正常生成so.接着继续ReBuild Project又报错了:Execution failed for task ':app:generateJsonModelDebug'.
> executing external native build for ndkBuild E:\DownLoad\MyApplication8\app\src\main\jni\android.mk
得,卡在这一步了。查了半天,都说要降低cmake版本。这是不可能的事了。。果断放弃。
============================================================================================================================================================================================================================

删除操作,后面再开始cmakebuild.gradle设置中删除下面这条设置externalNativeBuild{
            ndkBuild{
                arguments "NDK_APPLICATION_MK:=src/main/jni/application.mk"
                cFlags "-DTEST_C_FLAGS1","-DTEST_C_FLAG2"
                cppFlags "-DTEST_CPP_FLAGS1","-DTEST_CPP_FLAG2"

            }
      }

删除下面这条设置externalNativeBuild {
      ndkBuild {
            path file('src/main/jni/android.mk')
      }
    }再删除除android.mk,删除application.mk点一下sync now
============================================================================================================================================================================================================================
三、用CMake生成SO
ndk-build果断玩不动。还是继续CMAKE
在gradle.properties中,添加下面这条:ndk{
    moduleName "funjisuan"
}
在app层里的build.gradle中,android节点的设置。defaultConfig节点中添加下面内容:externalNativeBuild{
            cmake{

                abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64'//生成多个版本的so文件
            }
      }
defaultConfig节点外面,android节点里面添加下面内容: externalNativeBuild{
      cmake{
            path "CMakeLists.txt"//设置所要编写的C源码位置,以及编译后so文件的名字
      }
    }
完整设置如下:android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
      applicationId "com.example.myapplication"
      minSdkVersion 22
      targetSdkVersion 30
      versionCode 1
      versionName "1.0"

      testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
      externalNativeBuild{
            cmake{

                abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64'//生成多个版本的so文件
            }
      }
    }

    buildTypes {
      release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
      }
    }
    compileOptions {
      sourceCompatibility JavaVersion.VERSION_1_8
      targetCompatibility JavaVersion.VERSION_1_8
    }

    externalNativeBuild{
      cmake{
            path "CMakeLists.txt"//设置所要编写的C源码位置,以及编译后so文件的名字
      }
    }

}
在app层,新建CMakeLists.txt文件,操作:选中app,右键,New---FileCMakeLists.txt添加下面内容:# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.
#CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
      # 设置so文件名称.
      funjisuan

      # Sets the library as a shared library.
      SHARED
      # 设置这个so文件为共享.

      # Provides a relative path to your source file(s).
      # 设置这个so文件为共享.
      src/main/jni/bindNativeJisuan.c)

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
      log-lib

      # Specifies the name of the NDK library that
      # you want CMake to locate.
      log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
      # 制定目标库.
      funjisuan

      # Links the target library to the log library
      # included in the NDK.
      ${log-lib} )
好了就可以直接点上面的Build----Rebuild project
运行效果如下:


总结:动态注册中,native方法不是static,C方法中,需要用JNI_onLoad注册。后面生成so的操作过程是一样的。之前操作的直接返回一个static方法(返回字符串).最后还是用CMAKE生成SO。现在比较新的android studio版本,可以创建Native C++,只需要把C++层代码写一写就可以直接生成了。之所以搞这么老的操作,是想理解这个过程。以后写这种代码肯定直接创建Native C++项目。不必再这样折腾。

最后,不得不说的一句,代码逻辑有问题。点击计算按钮就闪退了。搞不动。睡觉。。
============================================================================================================================================================================================================================

现在编写SO创建Native C++项目。



Next,设置好项目名称,再Next ,选择C++标准。再点击finish就完成创建.

完了项目已经自动生成cpp文件,CMakeLists.txt。需要改动的地方就三个文件,MainActivity类里,因为system.loadlibrary写在这里,需要修改so名称直接在这里改。cpp文件名称可直接修改,然后实现代码完好。CMakeLists.txt,需要修改一下cpp被修改后的名称,还有LoadLibrary修改后的名称。就可以直接Build了。



============================================================================================================================================================================================================================

这又过了一天。昨天写的C代码居然因为一个字母导致异常退出了。
经过数次的调试,原来是c文件在FindClass时,写错了类文件名称。导致找不到jni类.所以再来修改一下。修改的地方是:
jint registNativeMethod(JNIEnv *env)
{
    char* strname="com/example/myapplication9/lstnjisuan";
    jclass funclass=(*env)->FindClass(env,"strname");
    //进行JAVA层注册,如果不等于0返回错误

    if(((*env)-> RegisterNatives(env, funclass,nativeMethod,sizeof(nativeMethod)/sizeof(nativeMethod)))!=0)
    {
      return JNI_ERR;
    }
    return JNI_OK;
}

原来写的是:
jclass funclass=(*env)->FindClass(env,"./listnjisuan");
现在改过来了。
简易器计算稍微正常了。没有对输入框对输入的数字进行判断。这种BUG以后再去补充。
运行效果如下:


这整个过程就算是完成了。
总结一下:
动态注册C就是通过JNI_onLoad来完成。在android的jni文档里有示例。h文件生不生成其实没关系,至少目前没关系,因为都在C文件实现了。只不过写C语言写习惯了,总会写个h文件进行声明。
上面提到的生成so方法两种:
1.把CMakeLists.txt文件设置完,build.gradle,还有build.properties设置一下,整个代码写完可以直接build就可以了。过程不算复杂。
2.不要创建默认的空项目,或者hello项目,选择Native C++项目,cpp代码写好,native代码写好。直接修改CMakeLists.txt的内容,cpp名称,so名称,就可以直接Build。

Destroyer 发表于 2020-10-24 21:23

贝优妮塔 发表于 2020-10-23 10:47
写so居然这么麻烦
比C++写dll 麻烦多了   
没怎么玩过java


so 约等于 dllso是在Android 平台运行的(linux也行),dll 是在window平台运行的,他这个只是借助Android studio来写so, linux可以直接写,用不了这么麻烦,只是Android 开发一般会用Android studio来写,方便和Android程序一起调试

欧雨鹏 发表于 2020-10-23 13:24

小骚 发表于 2020-10-23 08:42
那么问题来了.........为啥要用代码生成h或者cpp.......右键新建一个或者直接改后缀貌似都可以的吧........ ...

没问题的。目前写的只是没用到h文件。用javah命令创建h文件是,因为省去了再去写代码的步骤。目前的例子没用到h文件,其实不创建h文件也可以的。直接创建个.c或者.cpp把代码写进去就好。android studio中的Native C++项目,自动创建的就只有cpp文件,没有h文件。可见h文件不是必须的。

美美木耶 发表于 2020-10-23 02:14

6666,真不错

Agnehc 发表于 2020-10-23 05:54

有电复杂

dyyy 发表于 2020-10-23 07:13

有些看不明白,慢慢看,感谢分享

小骚 发表于 2020-10-23 08:42

那么问题来了.........为啥要用代码生成h或者cpp.......右键新建一个或者直接改后缀貌似都可以的吧.............我用着好像没毛病{:301_982:}

贝优妮塔 发表于 2020-10-23 10:47

小骚 发表于 2020-10-23 08:42
那么问题来了.........为啥要用代码生成h或者cpp.......右键新建一个或者直接改后缀貌似都可以的吧........ ...

写so居然这么麻烦
比C++写dll 麻烦多了   
没怎么玩过java
一直认为so=dll的
{:1_937:}

roc2030 发表于 2020-10-23 10:49

楼主威武!厉害厉害

xjcyxyx 发表于 2020-10-23 11:22

好复杂啊

老柴头 发表于 2020-10-23 11:44

楼主厉害!

xiaoaiai2468 发表于 2020-10-23 13:13

感谢大佬的分享,学习学习{:301_1000:}
页: [1] 2 3 4 5
查看完整版本: 折腾折腾用android studio去编写so--动态注册