1. 环境准备

1.1 安装JDK:jdk1.8.0_112

1.2 安装Android SDK

SDK可以安装指定的platforms和ndk-bundle。为了兼容性考虑,单独安装了版本比较老的android-ndk-r10b

1.3 安装VS2019

安装VS2019并选择:使用C++的移动开发。

1.4 连接开发手机

使用USB数据线连接开发手机并打开开发手机的USB调试选项。

2. 创建Android动态库工程

2.1 创建新项目

启动VS2019,选择创建新项目

2.2 选择项目类型

下拉框选择C++、Android,列表选择动态共享库(Android),单击下一

2.3 填写项目属性

填写项目名称:MyTestSo,选择创建位置,单击创

2.4 项目创建完成

3. 创建动态库测试项目

3.1 新建Android项目

在解决方案上单击鼠标右键,选择弹出菜单中的添加->新建项目菜单项。

3.2 选择项目类型

下拉框选择C++、Android,列表选择Native-Activity应用程序(Android),单击下一步

3.3 填写项目属性

填写项目名称:Test,单击创建

3.4 项目创建完成

3.5 ​​​​​​​添加引用

在左侧Test.NativeActivity项目下的引用上单击鼠标右键,选择弹出菜单:添加引用(R)…

选中MyTestSo,单击确定完成设置。

  1. 4. 设置IDE属性

选择VS2019菜单项:工具 -> 选项,打开选项设置页面。

选择跨平台 –> C++ -> Android,填写右边的开发工具目录。

  1. 5. 设置项目属性

直接编译创建出来的项目会出现一些如下所示的错误:

需要设置MyTestSo项目和Test.NativeActivity两个项目的编译属性,以下以MyTestSo项目为例。

打开MytestSo项目属性,选择左侧常规,修改右边的平台工具集为:GCC 4.9,目标API级别为android-L。

  1. 6. 编译运行

    6.1 修改动态库项目代码

在MyTestSo.cpp源码文件中增加测试函数test,代码如下:

void test()
{LOGI("Hello World From MyTestSo");
}

6.2 ​​​​​​​修改测试项目代码

在main.cpp源码文件中调用测试函数test,代码如下:

extern "C" void test();

test();

​​​​​​​6.3 编译运行项目

设置Test.Packaging项目为启动项目,选择编译并运行Test.Packaging项目,查看Logcat输出日志。

项目在有些低版本Android平台上运行可能会崩溃,解决方案参考第7节。

6.4 调试代码

在main.cpp或者MyTestSo.cpp中设置好断点,调试启动Test.Packaging项目,将会在设置的断点处中断,效果如下图所示:

7. 崩溃问题解决

项目在有些低版本Android平台上运行可能会崩溃,出现如下错误:

原因在于libTest.so库依赖了libMyTestSo.so库,项目在运行时加载libTest.so库之前并没有加载libMyTestSo.so库,从而导致了崩溃。解决方案为自定义项目启动类,在启动类里加载so库。

​​​​​​​7.1 自定义项目启动类

在项目Test.Packaging中添加目录结构:src/com/mytest,在mytest目录下创建java源文件MyTestActivity.java,内容如下:

package com.mytest;import android.app.NativeActivity;public class MyTestActivity extends NativeActivity
{static{System.loadLibrary("MyTestSo"); System.loadLibrary("Test"); }
}

 

7.2 修改AndroidManifest.xml

打开AndroidManifest.xml编辑内容,

  • android:hasCode 属性修改为:true
  • android:name 属性修改为:com.mytest.MyTestActivity

7.3 重新编译运行项目

附录:使用jar包

原文链接:https://retroscience.net/visual-studio-android-ndk-jar-files.html

Android NDK, JAR files, JNI, and Visual Studio

For those of you who don’t know, I have been a Visual Studio user for a long time now, amoung other forms of IDEs I’ve used Visual Studio the most. Something else I also love to use is the C programming language (I wish VS was more up to date for C but it’s good enough). One of the things you can do is develop for Android using NDK and Visual Studio which works fairly well, even though it is using Ant instead of Gradle, I find that it has suited all of my needs so far. That being said, I’m going to drop some tips here on how to make the development process a bit more friendly to be able to interact via JNI and native code.

Note: I am assuming you’ve setup Visual Studio and installed native android development

Update Ant

If you’ve installed Android native development through Visual Studio, you should have everything you need (NDK & SDK) inside of the C:/Microsoft folder. Something we need to do is tell the Ant build system to use a more modern version of JDK (OpenJDK) for building java code. To do this, open the C:/Microsoft/AndroidSDK/25/tools/ant/build.xml file in a text editor and locate the line that starts with <property name="java.target". Change the value of this to 1.7. Do the same thing for <property name="java.source". At this point you should see something like the following:

<!-- compilation options -->
<property name="java.encoding" value="UTF-8" />
<property name="java.target" value="1.7" />
<property name="java.source" value="1.7" />
<property name="java.compilerargs" value="" />
<property name="java.compiler.classpath" value="" />

project.properties

My project properties file in the .sln looks like the following:

# Project target
target=$(androidapilevel)
# Provide path to the directory where prebuilt external jar files are by setting jar.libs.dir=
jar.libs.dir=libs

AndroidManifest.xlm

Since we are going to be writing .jar files and possibly loading in external libraries at runtime, we will need to setup our project to have our own custom native activity code. Inside the AndroidManifest.xlm file you will need to find the android:hasCode="" value in the <application> tag and set it’s value to true. It should look similar to the following:

<application android:label="@string/app_name" android:hasCode="true"><!-- ... -->
</application>

Next we will want to set the <activity android:name="" value to our package and activity name that we will be creating. So if your activity class name is going to be FancyActivity then you should have something similar to the following:

<activity android:name="com.PackageName.FancyActivity" android:label="@string/app_name"><!-- ... -->
</activity>

Creating our custom activity

Since our full class path will be com.PackageName.FancyActivity we will need to create a few folders inside of our *.Packaging project in Visual studio. Create a folder path named src/com/PackageName/. Next create a file inside of the PackageName folder named FancyActivity.java. Below is the code you should have inside of FancyActivity.java:

package com.PackageName;
import android.app.NativeActivity;
public class FancyActivity extends NativeActivity
{static{//System.loadLibrary("other_lib");}
}

Notice the commented out line System.loadLibrary. You can call this as many times as needed, but all you need to do is replace "other_lib" with the name of your library, like System.loadLibrary("fmod"); or something similar. At this point you should be able to build without any issues.

Pro tip: You should always add System.loadLibrary("ProjectName"); where ProjectName is the name of the .so file that is generated for your NDK project build. This will allow you to call native functions from within your Java code (great for callbacks and the like).

Custom JAR files

Now that we’ve setup our activity to better interact with JNI and load other libraries, we are going to look at how to add our own .jar files and access the types within them from native code.

Building .jar files

Make sure and compile your code with -source 1.7 -target 1.7 so that it is matching Ant’s versions we setup earlier. After you’ve built your .class files, ensure your folder structure is correct as it relates to the package path. If your package path for your class(es) is package com.PackageName; then you should have the .class file within a folder structure com/PackageName/*.class. When you build your .jar file it should be for the whole folder structure.

Including .jar files in project

Now that you have your .jar file, you should create a folder named libs in your *.Packaging project. Place your .jar file into this folder and make sure to right click it and select Include In Project.

Accessing your code inside the .jar file

Lets assume for this part you’ve created a class named Dummy with a function that has the signature void SayHi(string name) which will print out “Hello, %s!” (%s = name input string of function). We will use JNI to access your code and invoke your method. Below is the code we will use to call our function. You can place it directly inside of your void android_main(struct android_app* state) function:

JNIEnv* env = NULL;
const ANativeActivity* activity = state->activity;
(*activity->vm)->AttachCurrentThread(activity->vm, &env, 0);jobject jobj = activity->clazz;
jclass clazz = (*env)->GetObjectClass(env, jobj);
jmethodID getClassLoader = (*env)->GetMethodID(env, clazz, "getClassLoader", "()Ljava/lang/ClassLoader;");
jobject cls = (*env)->CallObjectMethod(env, jobj, getClassLoader);
jclass classLoader = (*env)->FindClass(env, "java/lang/ClassLoader");
jmethodID findClass = (*env)->GetMethodID(env, classLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
jstring strClassName = (*env)->NewStringUTF(env, "com.PackageName.Dummy");
jclass fancyActivityClass = (jclass)((*env)->CallObjectMethod(env, cls, findClass, strClassName));
(*env)->DeleteLocalRef(env, strClassName);
jmethodID sayHi = (*env)->GetStaticMethodID(env, fancyActivityClass, "SayHi", "(Ljava/lang/String;)V");
jstring words = (*env)->NewStringUTF(env, "Brent");
(*env)->CallStaticVoidMethod(env, fancyActivityClass, sayHi, words);
(*env)->DeleteLocalRef(env, words);

​​​​​​​Now those who have had a little exposure with JNI might say “Can’t we just use the (*env)->FindClass method? While this may be true for normal Android built in classes, it is not true for our own custom class. The reasoning is that JNI can only look through what is currently on the stack, and believe it or not, even though our FancyActivity is running our code, it isn’t on the stack so we can’t even find it. So what we need to do is get the current activity, then find a method on it called getClassLoader. Once we have this function, we are free to load any class from anywhere that is loaded, even inside our .jar code.

Hope this helps people who are having trouble. It tooke me a full day to figure out all of this stuff because there isn’t anything straight forward on the internet, I had to dig really deep to find all the pieces to put this together!

使用VS2019开发调试Android动态库相关推荐

  1. 【Android NDK 开发】Ubuntu 函数库交叉编译 ( Android 动态库交叉编译 | Android 静态库交叉编译 )

    文章目录 I . Ubuntu 中交叉编译 Android 动态库 II . Ubuntu 中交叉编译 Android 静态库 I . Ubuntu 中交叉编译 Android 动态库 1 . 要编译 ...

  2. android 实现表格横向混动_Flutter混合开发和Android动态更新实践

    Flutter混合开发和Android动态更新实践 感谢闲鱼和csdn的文章给的思路: 本篇是实践性文章包含两部分 将Flutter工程编译后的文件集成到Android项目 将Flutter代码热更新 ...

  3. C++开发支持Android共享库(so)教程

    C++开发支持Android共享库(so)教程 概述: Android是运行于Linux上的移动系统,Android开发语言是java,Linux开发语言是C/C++.虽然google和java为An ...

  4. (成功案例超详细保姆级)vs2019 opencv qt创建动态库被C#调用

    之前有个项目关于图像处理,既用到了opencv,还二次开发了相机提供的动态库.一开始我是用QT写的,然后发现人家只需要我提供一个库函数调用就可以了,但是他是用C#写的.没办法,到处找资料,但是没有找到 ...

  5. 成功案例超详细-vs2019 opencv qt创建动态库被C#调用

    之前有个项目关于图像处理,既用到了opencv,还二次开发了相机提供的动态库.一开始我是用QT写的,然后发现人家只需要我提供一个库函数调用就可以了,但是他是用C#写的.没办法,到处找资料,但是没有找到 ...

  6. FFmpeg编译成Android动态库

    项目需要,网上也有现成的FFmpeg Android动态库,但是本着亲力亲为的宗旨,做了不断地尝试,最终也是成功了,在此做一个笔记,以备日后查阅. 附上给我帮助的资料链接: 王英豪大神的博客 雷霄骅大 ...

  7. android 动态库 后缀,Android Robolectric加载运行本地So动态库

    前言 Robolectric 是 Android 的单元测试框架,运行无需 Android 真机环境直接运行在 JVM 之上,所以在 test case 运行速度效率上有了很大提升,接近于 Java ...

  8. vs2017下开发C++MFC动态库实现

    2019独角兽企业重金招聘Python工程师标准>>> 今天无意间浏览了一些关于vs2017新功能的介绍,特别是微软发部了Visual Studio Installer,这个集成安装 ...

  9. linux下项目开发加载动态库:ldconfig与 /etc/ld.so.conf

    场景:自己开发一个项目,程序里包含一些自定义动态库.运行,需要加载这些动态库. 假如这些库在/pro/output/lib/下面,可执行程序在/pro/output/bin/下面. 那么,我们需要: ...

最新文章

  1. CTA核心技术及应用峰会开幕!(附第二日参会攻略)
  2. 传真故障排除示例--编码不一致导致传真失败
  3. 大数据WEB阶段Spring框架(一)IOC控制反转、DI注入依赖
  4. javame_JavaME:Google静态地图API
  5. mysql 酒店管理设计_酒店管理系统的设计与实现(Myeclipse,MySQL)
  6. 饭卡可以用水冲洗吗_薄壁不锈钢水管真的可以满足大众用水健康管道的要求吗?...
  7. python line strip_Python进阶---python strip() split()函数实战(转)
  8. java对excel加密_Java 加密、解密Excel文档
  9. Torch7框架学习资料整理
  10. 关于智能家居的四大思维误区 并非你想的那样
  11. dh协议c语言代码,openssl开源程序dh算法解析之dh_ameth.c
  12. 电气绘图软件EPLAN在WIN10详细安装教程
  13. 第二证券|七位投资专家指点2023 战略性看好A股 市场将提供更多机会
  14. 【技术邻】基于有限元方法的整车风噪仿真分析
  15. 用 GitHub 搭建静态博客太繁琐?用这个小工具实现「傻瓜式」发布!
  16. 油气管道供应可视化数据大屏:连点成线,打破信息孤岛
  17. matlab abc dq,关于matlab及pscad中abc2dq模块的使用.doc
  18. NPOI使用手册 (操作Excel)
  19. [每天get点新技能]搜商——你不知道的搜索概念:元搜索
  20. android shape 画虚线

热门文章

  1. 移动硬盘格式化数据恢复图文介绍
  2. 虚幻4增强现实Demo
  3. 最快速的寻路算法 Jump Point Search
  4. diskgenius重建分区表
  5. 银行从业资格证 个人理财 各种年金计算公式总结
  6. JSP+ssm计算机毕业设计刀具管理系统的设计与实现rhp57【源码、数据库、LW、部署】
  7. 视频图片加文字的二维码怎么做?教你在线制作二维码
  8. win10出现win10系统即将过期,请激活的处理办法
  9. 明年北京拟取消春季高考
  10. 华为手机的备忘录有定时提醒的功能吗 华为手机备忘录便签提醒教程