JNI

使用Android Studio 进行NDK开发和调试

那年仲夏 提交于 2019-12-07 21:08:07
尽管Android Studio已经越来越流行了,但很多人还是习惯于Eclipse或源码环境下开发JNI应用。个人认为使用Android Studio作NDK开发是必然趋势,所以本文将简单介绍如何在Android Studio上实现NDK开发。 简介 JNI JNI 是Java Native Inteface的缩写,是Java中定义的一种用于连接Java和C/C++接口的一种实现方式。 NDK NDK 是 Native Developmentit的缩写,是Google在Android开发中提供的一套用于快速创建native工程的一个工具。 使用这个工具可以很方便的编写和调试JNI的代码。 NDK可从 官网 或 AndroidDevTools (个人网站)下载。 Gradle Gradle 是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置。 以往Android NDK开发需要在Eclipse或源码环境下,建立并配置Android.mk和Application.mk,且还要通过java命令生成.h头文件,才能编译生成so库。但在Android Studio中这些步骤都不需要,因为Gradle足够强大,只需配置Gradle即可编译生成so库。 gradle-experimental插件

Android面试之----谈谈你对Java中Native关键字的认识

时间秒杀一切 提交于 2019-12-07 21:07:22
JNI是J ava Native Interface的 缩写。从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。 使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序 的性能。JNI标准至少保证本地代码能工作在任何Java 虚拟机实现下。 JNI(Java Native Interface)的书写步骤 ·编写带有native声明的方法的java类 ·使用javac命令编译所编写的java类 ·使用javah ?jni java类名生成扩展名为h的头文件 ·使用C/C++(或者其他编程想语言)实现本地方法 ·将C/C++编写的文件生成动态连接库 1) 编写java程序: 这里以HelloWorld为例。 代码1: class HelloWorld { public native void displayHelloWorld(); static { System.loadLibrary("hello"); } public static void

简单的安卓应用授权认证(JNI)

痞子三分冷 提交于 2019-12-07 13:56:21
最近一直在做公司的一个安卓开发框架,含so库,接近尾声了,领导提出一个需求,要求使用这个框架的开发者必须有我们的授权才可以,但是对方发布的应用后又不能被此授权限制——要不然所有的应用都来要授权那就麻烦了。 分析: 既然是限制开发者,那么就必须要区分debug版本和release版本,也就是框架的授权限制功能只对debug版本有效,而对release版本无效;然后就是需要一个调试设备的一个唯一ID,这样授权码是绑定在固定的设备的,只要有新的调试设备就需要新的授权码,一般公司里也就是十几个设备吧,这个申请量级完全可以接受。 思路: 因为正好这个框架需要so库的支持,这样在so库加载时的int JNI_OnLoad(JavaVM* jvm, void* reserved)方法中可以完成验证。 关于debug和release版本的区分,安卓系统提供了一个debugable属性可以实现,只要是从Eclipse或者ADT的集成环境里直接运行或者调试,都可以判断出是否是debug版本; 关于安卓设备的ID,安卓本身提供好几种ID的获取,我最终使用的是security类的ID, Settings.Secure.getString(ContentResolver, Settings.Secure.ANDROID_ID),这个ID是在安卓设备第一次启动的时候自动生成的,如果刷机的话则可能会改变。

卸载Android app弹出浏览器的一种实现

◇◆丶佛笑我妖孽 提交于 2019-12-07 12:04:32
卸载Android应用程序时,经常会弹出网页,做些用户数据的调查统计。 Android是可以获取到其它应用被卸载掉这个事件,但是并不能获取自身被卸载这个事件。从纯粹的java层是没法实现的, 本文介绍一种方法来实现它。 原理 简单来说就是创建后台进程,监控文件夹的删除事件。比如说app的包名是com.myname.myapp,后台进程监控的文件夹就是/data/data/com.myname.myapp。如何监控文件夹被删除这一事件,主要用的是inotify系列函数,这在 jni中的进程通讯的另一种实现方式 有介绍。 注意点 后台进程只需要一个就行了,不需要多个的,之前我注意到企鹅的一款产品做这个功能时,后台启动了多个进程。如何实现?可以参考 Android JNI层确保只有一个进程的一个实现 ,提供一种思路。 几种重点测试情形:a. 清理app的数据 b.升级app c. 强制关闭app,然后重启app。 代码 github地址 uninstallWatcher 代码实现以及demo都有了,接口也已经封装好,判断后台进程是否唯一,有点过于简单, 欢迎完善代码 。 代码使用也很简单。 public class DemoApp extends Application{ @Override public void onCreate() { Log.i("UninstallDemoApp

JNI入门中helloworld常见问题

走远了吗. 提交于 2019-12-07 11:58:13
看了我转载的那篇JNI入门感觉确实写得很好,但是配置细节没怎么说明,我这里说明一下。 主要是按照完成helloworld这个程序的步骤出现的问题。所有的程 序都是通过命令行来编译的。 问题一:NotClassDeff....Error 当然了这个问题绝对是classpath没有配置好,.;... 这个东西想必大家已经很熟悉了,不过有两点需要说明:1.注意文件路径中斜杠的方向,2.在win7中配置好环境变量不需要重新启动系统,只需要重新启动命令行。解决了这个问题你应该就可以得到.class文件 问题二:javah 不是命令或文件。。。 或javac 不是命令或文件。。。 这是因为没有设置好path,只要把java安装目录/bin,放在path中即可,还有win7只需要重启命令行。解决了这两个问题你就可以得到 hello.h文件了 问题三:在写好c程序后使用cl命令编译成dll会出现:XXX.lib not find 。。。 或 stdio.h not find 这就像java命令找不到 classpath一样, 只要添加环境变量 include = vc安装目录下的include文件;lib=vc安装目录下的lib文件即可,重启命令行。下面你就会得到dll文件。 其他的一些问题很可能是由于你的文件名,属性名等等没有对应好而造成的,请仔细检查。 "java中System

android NDK开发入门。

心已入冬 提交于 2019-12-07 09:37:45
关于 NDK 的使用,首先需要了解一个概念: JNI 。什么是 JNI ? 2.1 Hello-jni 这个是 NDK 自带的例子程序,安装官方网站的说明,一步步来,应该没有什么问题,这里就不细说了。 2.2 My God I did it 学习的第一步,就是模仿。我们依照上面 Hello-jni 的例子,在创建自己的 NDK 程序。在此过程中,对相关的内容和概念进行分析和说明。 首先, 在工程的 src 夹子下用来放置 Java 文件。我们打开 Eclipse ,然后新建一个 Android 工程,工程名就叫 MyJNI ,工程路径选择我们创建的 NDK 的路径。这里需要注意的是,工程名,包名等,需要和上面的 c 文件中的保持一致。 (Java _ com_jpf_myjni _ MyJNI _ stringFromJNI) 工程建立好后,编辑 src/com/jpf/myjni/MyJNI.java 文件,内容如下: package com.jpf.myjni; import android.app.Activity; import android.widget.TextView; import android.os.Bundle; public class MyJNI extends Activity { /** Called when the activity is

jni中的进程通讯的另一种实现方式

你说的曾经没有我的故事 提交于 2019-12-06 20:26:17
在adb shell中执行ps命令常看到后台进程,这些后台进程很多都是在JNI层创建的,并非普通的Android进程,那么问题来了,如何让进程通讯呢? 方式有很多种。 1. 创建socket进行通讯,“127.0.0.1”+ 特定的端口号。这种方式很常用。 2. 管道,父进程和子进程是可以通过管道来读写数据的。这个比较常用。 3. 直接写入特定的文件,这也是本博文要介绍的一种实现,这个估计用的很少,但是在某些情况下使用很有意思,尤其是对主进程来说,只需要写入文件。 Android是从Linux上修改过来的,Linux上不少api也是能够直接在Android上使用的,inotify就是其中一个,用于监控文件系统中的事件。当子进程监控特定的文件,父进程写入该文件时,子进程是能获取到该文件被修改的事件的,也就能直接读取文件中的内容了。以下是代码片段 size_t readBytes = read(fileDescriptor, p_buf, EVENT_BUF_LEN); int k = 0; while (k < readBytes){ struct inotify_event *event = ( struct inotify_event * )(p_buf + k); if (event->len > 0){ kesyPrintf("event.name=%s\n", event-

Android 增量更新实例(Smart App Updates)

吃可爱长大的小学妹 提交于 2019-12-06 12:26:14
目录[-] 官方说明 实现原理 实现 (1)生成差异包 (2)使用旧apk+差异包,在客户端合成新apk 注意事项 demo 自从 Android 4.1 开始,Google引入了应用程序的增量更新。 官方说明 Smart app updates is a new feature of Google Play that introduces a better way of delivering app updates to devices. When developers publish an update, Google Play now delivers only the bits that have changed to devices, rather than the entire APK. This makes the updates much lighter-weight in most cases, so they are faster to download, save the device’s battery, and conserve bandwidth usage on users’ mobile data plan. On average, a smart app update is about 1/3 the sizeof a full APK

JNI 调用,C++ invoke C# dll return to java(见git代码)

旧街凉风 提交于 2019-12-06 09:19:48
Java无法直接调用C# dll,需要通过经过桥接的方式,进行中继转发一下请求。查阅大量资料,做了大量实验,不停的调试、排错之后,期间试过jni4net,不过这个插件需要 修改原有的C# DLL内容,还会生成一些额外的Java代码,jni4net侵入性太多,将它排除。最后通过管理性的C++桥接方式,成功完成了Java调用C# DLL。 国内很多文章都是只有文章,没有在文中附上完整的代码工程,导致读者做实验时非常麻烦。而老外经常会带上完整的代码工程,这让读者做实验时参考起来非常方便。本文附上完整的Java、C++、CSharp代码工程,供大家参考。 实验环境: 64位 Win 7 jdk1.7.0_51 Eclipse 4.3.1 Visual Studio 2010 具体的实现步骤如下: 1,新建一个Java项目TestJNI,定义一个Java客户端类 TestJNI.java Java代码 package msg; public class TestJNI { public native boolean MasSentMessage(String a, String b); public native int add(int a, int b); public native String submit(String a, String b); public native

Android中JNI编程详解

你说的曾经没有我的故事 提交于 2019-12-06 08:34:45
Android 系统不允许一个纯粹使用C/C++的程序出现,它要求必须是通过Java代码嵌入Native C/C++——即通过JNI的方式来使用本地(Native)代码。因此JNI对Android底层开发人员非常重要。 如何将.so文件打包到.APK 让我们 先 从最简单的情况开始,假如已有一个JNI实现——libxxx.so文件,那么如何在APK中使用它呢? 在我最初写类似程序的时候,我会将libxxx.so文件push到/system/lib/目录下,然后在Java代码中执行System.loadLibrary(xxx),这是个可行的做法,但需要取得/system/lib 目录 的写权限(模拟器通过adb remount取得该权限)。但模拟器 重启之 后libxxx.so文件会消失。现在 我找到了更好的方法,把.so文件打包到apk中分发给最终用户,不管是模拟器 或者 真机 ,都不再需要system分区的写权限。实现步骤如下: 1、在你的项目根目录下建立libs/armeabi目录; 2、将libxxx.so文件copy到 libs/armeabi/下; 3、此时ADT插件自动编译输出的.apk文件中已经包括.so文件了; 4、安装APK文件,即可直接使用JNI中的方法; 我想还需要简单说明一下libxxx.so的命名规则,沿袭Linux传统,lib.so是类库文件名称的格式