├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── glumes
│ │ └── androidcppsolib
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ └── native-lib.cpp
│ ├── java
│ │ └── com
│ │ │ └── glumes
│ │ │ └── androidcppsolib
│ │ │ ├── MainActivity.kt
│ │ │ ├── SoApplication.kt
│ │ │ ├── activity
│ │ │ ├── AbstractPlayerActivity.kt
│ │ │ ├── AviBitmapPlayerActivity.kt
│ │ │ ├── AviOpenGLPlayerActivity.kt
│ │ │ ├── BitmapOperationActivity.kt
│ │ │ ├── InfoManageActivity.kt
│ │ │ └── JNIMethodActivity.kt
│ │ │ ├── base
│ │ │ └── BaseListActivity.kt
│ │ │ ├── binder
│ │ │ ├── InfoManagerBinder.kt
│ │ │ ├── JNIMethodBinder.kt
│ │ │ └── MainListItemBinder.kt
│ │ │ ├── handler
│ │ │ └── JNIOperationHandler.kt
│ │ │ ├── utils
│ │ │ └── DataBindingUtils.java
│ │ │ └── widget
│ │ │ ├── CircleImageView.kt
│ │ │ └── ItemInfo.kt
│ └── res
│ │ ├── drawable
│ │ ├── avatar.png
│ │ ├── info_card_bg.xml
│ │ ├── info_item_bg.xml
│ │ ├── material_flat.png
│ │ ├── minus.png
│ │ ├── plus.png
│ │ └── woman_16.png
│ │ ├── layout
│ │ ├── activity_avi_open_glplayer.xml
│ │ ├── activity_avi_player.xml
│ │ ├── activity_base_list.xml
│ │ ├── activity_bitmap_operation.xml
│ │ ├── activity_info_manager.xml
│ │ ├── info_card.xml
│ │ ├── item_jni_method.xml
│ │ └── item_main.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── glumes
│ └── androidcppsolib
│ └── ExampleUnitTest.java
├── build.gradle
├── cppso
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── glumes
│ │ └── cppso
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ ├── avilib
│ │ │ ├── avidump.c
│ │ │ ├── avilib.c
│ │ │ ├── avilib.h
│ │ │ ├── platform.h
│ │ │ ├── platform_posix.c
│ │ │ ├── platform_tc.c
│ │ │ ├── static_avilib.h
│ │ │ ├── static_wavlib.h
│ │ │ ├── wavlib.c
│ │ │ └── wavlib.h
│ │ ├── aviplayer
│ │ │ ├── AviPlayer.cpp
│ │ │ └── AviPlayer.h
│ │ ├── common
│ │ │ ├── commonutil.cpp
│ │ │ ├── commonutil.h
│ │ │ └── logutil.h
│ │ ├── infomanager
│ │ │ ├── LoadManager.cpp
│ │ │ ├── Student.cpp
│ │ │ └── Student.h
│ │ └── jnioperations
│ │ │ ├── array-type-operation.cpp
│ │ │ ├── basic-type-operation.cpp
│ │ │ ├── bitmap_operation.cpp
│ │ │ ├── cache_filed_and_method.cpp
│ │ │ ├── exceptions-operations.cpp
│ │ │ ├── filed_and_method_operation.cpp
│ │ │ ├── invoke_constructor.cpp
│ │ │ ├── local_and_global_references.cpp
│ │ │ ├── native_onload.cpp
│ │ │ ├── string-type-operation.cpp
│ │ │ ├── thread_operation.cpp
│ │ │ └── thread_operation.h
│ ├── java
│ │ ├── com
│ │ │ └── glumes
│ │ │ │ └── cppso
│ │ │ │ ├── aviplayer
│ │ │ │ └── AviPlayer.java
│ │ │ │ ├── infomanager
│ │ │ │ └── StudentInfoLoader.java
│ │ │ │ ├── jnioperations
│ │ │ │ ├── ArrayTypeOps.java
│ │ │ │ ├── BaseOperation.java
│ │ │ │ ├── BasicTypeOps.java
│ │ │ │ ├── BitmapOps.java
│ │ │ │ ├── CacheFieldAndMethodOps.java
│ │ │ │ ├── ExceptionOps.java
│ │ │ │ ├── FieldAndMethodOps.java
│ │ │ │ ├── InvokeConstructorOps.java
│ │ │ │ ├── LocalAndGlobalReferenceOps.java
│ │ │ │ ├── NativeOnLoadOps.java
│ │ │ │ ├── NoOperation.java
│ │ │ │ ├── OperationsFactory.java
│ │ │ │ ├── StringTypeOps.java
│ │ │ │ └── ThreadOps.java
│ │ │ │ ├── model
│ │ │ │ ├── Animal.java
│ │ │ │ └── Cat.java
│ │ │ │ └── utils
│ │ │ │ ├── Constants.kt
│ │ │ │ └── LogUtil.kt
│ │ ├── com_glumes_cppso_aviplayer_AviPlayer.h
│ │ └── com_glumes_cppso_jnioperations_BitmapOps.h
│ └── res
│ │ └── values
│ │ └── strings.xml
│ └── test
│ └── java
│ └── com
│ └── glumes
│ └── cppso
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
11 |
12 |
13 | .idea/
14 |
15 | gradle/
16 |
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > 该项目对应的视频课程已在慕课网上线: http://www.imooc.com/learn/1212
2 |
3 |
4 | # Android NDK 开发实践之路
5 |
6 | 在 Android 开发中使用 JNI 和 NDK 技术。
7 |
8 | ## JNI 基础准备
9 |
10 | JNI 全称:**Java Native Interface**。
11 |
12 | 它是独立于 Android 的一套接口,可以实现 Java 代码与 C/C++ 代码之间的交互。
13 |
14 | 打好了 JNI 的基础,才会在 NDK 开发时更加得心应手。
15 |
16 | 输出以下博客:
17 |
18 | * [Android JNI 基本操作](https://glumes.com/post/android/android-jni-basic-operation/)
19 | * [Android JNI 数组 操作](https://glumes.com/post/android/android-jni-array-operation/)
20 | * [Android 通过 JNI 访问 Java 字段和方法调用](https://glumes.com/post/android/android-jni-access-field-and-method/)
21 | * [Android 通过 JNI 调用 Java 类的构造方法和父类的方法](https://glumes.com/post/android/android-jni-invoke-constructor-method-and-super-method/)
22 | * [Android JNI 调用时缓存字段和方法 ID](https://glumes.com/post/android/android-jni-cache-fieldid-and-methodid/)
23 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'kotlin-kapt'
5 |
6 | android {
7 | compileSdkVersion 26
8 |
9 | defaultConfig {
10 | applicationId "com.glumes.androidcppsolib"
11 | minSdkVersion 22
12 | targetSdkVersion 26
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
16 | externalNativeBuild {
17 | cmake {
18 | cppFlags "-std=c++11"
19 | }
20 | }
21 |
22 | ndk {
23 | abiFilters 'arm64-v8a', 'x86', 'x86_64', 'armeabi-v7a'
24 | }
25 |
26 | }
27 | buildTypes {
28 | release {
29 | minifyEnabled false
30 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
31 | }
32 | }
33 |
34 | externalNativeBuild {
35 | cmake {
36 | path "src/main/cpp/CMakeLists.txt"
37 | }
38 | }
39 |
40 | dataBinding {
41 | enabled = true
42 | }
43 |
44 | }
45 |
46 | dependencies {
47 | implementation fileTree(dir: 'libs', include: ['*.jar'])
48 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
49 | exclude group: 'com.android.support', module: 'support-annotations'
50 | })
51 |
52 | implementation 'com.android.support:design:26.1.0'
53 | implementation 'com.android.support:cardview-v7:26.1.0'
54 | implementation 'com.android.support:appcompat-v7:26.1.0'
55 |
56 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
57 | testImplementation 'junit:junit:4.12'
58 | implementation 'com.android.support:recyclerview-v7:26.1.0'
59 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
60 |
61 |
62 |
63 | implementation project(':cppso')
64 |
65 | // kapt 'com.android.databinding:compiler:3.1.0'
66 |
67 | implementation 'com.jakewharton.timber:timber:4.6.1'
68 | // debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
69 | // releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
70 |
71 | // 写 demo 用的库
72 | implementation 'com.glumes:sampleutil:0.0.2'
73 | implementation 'com.glumes:databindingadapter:0.0.3'
74 |
75 | implementation 'com.tbruyelle.rxpermissions2:rxpermissions:0.9.5@aar'
76 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
77 | implementation 'io.reactivex.rxjava2:rxjava:2.1.14'
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/glumes/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/glumes/androidcppsolib/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.glumes.androidcppsolib", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html
3 |
4 | # Sets the minimum version of CMake required to build the native library.
5 |
6 | cmake_minimum_required(VERSION 3.4.1)
7 |
8 | # Creates and names a library, sets it as either STATIC
9 | # or SHARED, and provides the relative paths to its source code.
10 | # You can define multiple libraries, and CMake builds them for you.
11 | # Gradle automatically packages shared libraries with your APK.
12 |
13 | add_library( # Sets the name of the library.
14 | native-lib
15 |
16 | # Sets the library as a shared library.
17 | SHARED
18 |
19 | # Provides a relative path to your source file(s).
20 | ${CMAKE_SOURCE_DIR}/native-lib.cpp )
21 |
22 |
23 | # Searches for a specified prebuilt library and stores the path as a
24 | # variable. Because CMake includes system libraries in the search path by
25 | # default, you only need to specify the name of the public NDK library
26 | # you want to add. CMake verifies that the library exists before
27 | # completing its build.
28 |
29 | find_library( # Sets the name of the path variable.
30 | log-lib
31 |
32 | # Specifies the name of the NDK library that
33 | # you want CMake to locate.
34 | log )
35 |
36 |
37 |
38 | # Specifies libraries CMake should link to your target library. You
39 | # can link multiple libraries, such as libraries you define in this
40 | # build script, prebuilt third-party libraries, or system libraries.
41 |
42 | target_link_libraries( # Specifies the target library.
43 | native-lib
44 |
45 | # Links the target library to the log library
46 | # included in the NDK.
47 | ${log-lib} )
48 |
--------------------------------------------------------------------------------
/app/src/main/cpp/native-lib.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 |
5 | extern "C"
6 | JNIEXPORT void JNICALL
7 | Java_com_glumes_androidcppsolib_MainActivity_outputString(JNIEnv *env, jobject instance,
8 | jstring msg_) {
9 | const char *msg = env->GetStringUTFChars(msg_, 0);
10 |
11 | env->ReleaseStringUTFChars(msg_, msg);
12 | }
13 |
14 | extern "C"
15 | JNIEXPORT jstring JNICALL
16 | Java_com_glumes_androidcppsolib_MainActivity_stringFromJNI(
17 | JNIEnv *env,
18 | jobject /* this */) {
19 | std::string hello = "Hello from C++";
20 |
21 | return env->NewStringUTF(hello.c_str());
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib
2 |
3 |
4 | import android.graphics.Color
5 | import android.os.Bundle
6 | import android.support.v7.widget.RecyclerView
7 | import android.support.v7.widget.Toolbar
8 | import com.glumes.androidcppsolib.base.BaseListActivity
9 | import com.glumes.androidcppsolib.binder.MainItem
10 | import com.glumes.androidcppsolib.binder.MainListItemBinder
11 | import com.glumes.cppso.utils.JUMP_BITMAP_OPERATION_ACTIVITY
12 | import com.glumes.cppso.utils.JUMP_GRAPHIC_API_ACTIVITY
13 | import com.glumes.cppso.utils.JUMP_INFO_MANAGER_ACTIVITY
14 | import com.glumes.cppso.utils.JUMP_JNI_METHOD_ACTIVITY
15 | import com.glumes.databindingadapter.DataBindingAdapter
16 | import com.glumes.databindingadapter.Items
17 |
18 | class MainActivity : BaseListActivity() {
19 |
20 |
21 | private val items = Items()
22 |
23 | override fun onCreate(savedInstanceState: Bundle?) {
24 | super.onCreate(savedInstanceState)
25 | items.add(MainItem("JNI • 基础操作", JUMP_JNI_METHOD_ACTIVITY))
26 | items.add(MainItem("JNI 基础实践 • 学生信息管理", JUMP_INFO_MANAGER_ACTIVITY))
27 | items.add(MainItem("Native • 图形 API ", JUMP_GRAPHIC_API_ACTIVITY))
28 | items.add(MainItem("JNI • Bitmap 操作 ", JUMP_BITMAP_OPERATION_ACTIVITY))
29 | }
30 |
31 | override fun setUpToolbar(toolbar: Toolbar) {
32 | toolbar.title = resources.getString(R.string.app_name)
33 | toolbar.setTitleTextColor(Color.WHITE)
34 | }
35 |
36 |
37 | override fun initAdapter(): RecyclerView.Adapter {
38 |
39 | val mAdapter = DataBindingAdapter()
40 | mAdapter.map(MainItem::class.java, MainListItemBinder())
41 | .setItems(items)
42 |
43 | return mAdapter
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/SoApplication.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib
2 |
3 | //import com.squareup.leakcanary.LeakCanary
4 | import android.app.Application
5 | import timber.log.Timber
6 | import timber.log.Timber.DebugTree
7 |
8 |
9 | /**
10 | * Created by glumes on 28/02/2018
11 | */
12 | class SoApplication : Application() {
13 |
14 | override fun onCreate() {
15 | super.onCreate()
16 | initLeakCanary()
17 | initTimber()
18 |
19 | }
20 |
21 | private fun initTimber() {
22 | if (BuildConfig.DEBUG) {
23 | Timber.plant(DebugTree())
24 | }
25 | }
26 |
27 | private fun initLeakCanary() {
28 | // if (LeakCanary.isInAnalyzerProcess(this)) {
29 | // // This process is dedicated to LeakCanary for heap analysis.
30 | // // You should not init your app in this process.
31 | // return
32 | // }
33 | // LeakCanary.install(this)
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/AbstractPlayerActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 | import android.support.v7.app.AppCompatActivity
4 | import com.glumes.cppso.aviplayer.AviPlayer
5 |
6 | /**
7 | * @Author glumes
8 | */
9 | abstract class AbstractPlayerActivity : AppCompatActivity() {
10 |
11 | protected var mAvi: Long = 0L
12 |
13 |
14 | override fun onStart() {
15 | super.onStart()
16 | }
17 |
18 |
19 | override fun onStop() {
20 | super.onStop()
21 | if (mAvi != 0L) {
22 | AviPlayer.close(mAvi)
23 | mAvi = 0
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/AviBitmapPlayerActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 | import android.Manifest
4 | import android.graphics.Bitmap
5 | import android.support.v7.app.AppCompatActivity
6 | import android.os.Bundle
7 | import android.os.Environment
8 | import android.view.SurfaceHolder
9 | import android.view.SurfaceView
10 | import android.widget.Toast
11 | import com.glumes.androidcppsolib.R
12 | import com.glumes.cppso.aviplayer.AviPlayer
13 | import com.glumes.cppso.utils.LogUtil
14 | import com.tbruyelle.rxpermissions2.RxPermissions
15 | import java.io.File
16 | import java.util.concurrent.atomic.AtomicBoolean
17 |
18 | class AviBitmapPlayerActivity : AbstractPlayerActivity() {
19 |
20 | private val path = Environment.getExternalStorageDirectory().toString() + File.separator + "galleon.avi"
21 |
22 | private lateinit var mSurfaceView: SurfaceView
23 |
24 | private var isPlaying = AtomicBoolean()
25 |
26 | private var surfaceHolder: SurfaceHolder? = null
27 |
28 | private lateinit var rxPermissions: RxPermissions
29 |
30 | private val surfaceHolderCallback = object : SurfaceHolder.Callback {
31 |
32 | override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {
33 | }
34 |
35 | override fun surfaceDestroyed(holder: SurfaceHolder?) {
36 | isPlaying.set(false)
37 | }
38 |
39 | override fun surfaceCreated(holder: SurfaceHolder?) {
40 | isPlaying.set(true)
41 | Thread(renderer).start()
42 | }
43 | }
44 |
45 | private val renderer = Runnable {
46 | val bitmap = Bitmap.createBitmap(
47 | AviPlayer.getWidth(mAvi),
48 | AviPlayer.getHeight(mAvi),
49 | Bitmap.Config.RGB_565
50 | )
51 | val frameDelay = (1000 / AviPlayer.getFrameRate(mAvi)).toLong()
52 |
53 | while (isPlaying.get()) {
54 | AviPlayer.render(mAvi, bitmap)
55 | val canvas = surfaceHolder!!.lockCanvas()
56 | if (canvas != null) {
57 | canvas.drawBitmap(bitmap, 0f, 0f, null)
58 | surfaceHolder!!.unlockCanvasAndPost(canvas)
59 | Thread.sleep(frameDelay)
60 | }
61 | }
62 | }
63 |
64 | override fun onCreate(savedInstanceState: Bundle?) {
65 | super.onCreate(savedInstanceState)
66 | setContentView(R.layout.activity_avi_player)
67 |
68 | mSurfaceView = findViewById(R.id.surfaceView)
69 |
70 | rxPermissions = RxPermissions(this)
71 |
72 | rxPermissions.request(Manifest.permission.READ_EXTERNAL_STORAGE)
73 | .subscribe {
74 | if (it) {
75 | preparePlay()
76 | } else {
77 | Toast.makeText(this, "No Permission", Toast.LENGTH_SHORT).show()
78 | }
79 | }
80 | }
81 |
82 | private fun preparePlay() {
83 | if (File(path).exists()) {
84 |
85 | mAvi = AviPlayer.open(path)
86 |
87 | printAVIInfo()
88 |
89 | surfaceHolder = mSurfaceView.holder
90 |
91 | surfaceHolder!!.addCallback(surfaceHolderCallback)
92 | } else {
93 | Toast.makeText(this, "File not exist", Toast.LENGTH_SHORT).show()
94 | }
95 | }
96 |
97 |
98 | private fun printAVIInfo() {
99 | LogUtil.d("file path is $path")
100 | LogUtil.d("get avi id is $mAvi")
101 | LogUtil.d("get avi width is " + AviPlayer.getWidth(mAvi))
102 | LogUtil.d("get avi height is " + AviPlayer.getHeight(mAvi))
103 | LogUtil.d("get avi frameRate is " + AviPlayer.getFrameRate(mAvi))
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/AviOpenGLPlayerActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 | import android.opengl.GLSurfaceView
4 | import android.support.v7.app.AppCompatActivity
5 | import android.os.Bundle
6 | import com.glumes.androidcppsolib.R
7 | import com.glumes.cppso.aviplayer.AviPlayer
8 | import java.util.concurrent.atomic.AtomicBoolean
9 | import javax.microedition.khronos.egl.EGLConfig
10 | import javax.microedition.khronos.opengles.GL10
11 |
12 | class AviOpenGLPlayerActivity : AppCompatActivity() {
13 |
14 |
15 | private var isPlaying = AtomicBoolean()
16 |
17 | private var instance: Long = 0
18 | private var mAvi: Long = 0L
19 |
20 | private lateinit var glSurfaceView: GLSurfaceView
21 |
22 | override fun onCreate(savedInstanceState: Bundle?) {
23 | super.onCreate(savedInstanceState)
24 | setContentView(R.layout.activity_avi_open_glplayer)
25 |
26 | glSurfaceView = findViewById(R.id.glsurfaceview)
27 |
28 |
29 | }
30 |
31 | override fun onStart() {
32 | super.onStart()
33 | instance = AviPlayer.init(mAvi)
34 | }
35 |
36 | override fun onResume() {
37 | super.onResume()
38 | }
39 |
40 | override fun onPause() {
41 | super.onPause()
42 | }
43 |
44 | override fun onStop() {
45 | super.onStop()
46 | }
47 |
48 | private val renderer = object :GLSurfaceView.Renderer{
49 |
50 | override fun onDrawFrame(gl: GL10?) {
51 | }
52 |
53 | override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
54 | }
55 |
56 | override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
57 | // initSurface(instance,mAvi)
58 | }
59 |
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/BitmapOperationActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 | import android.graphics.Bitmap
4 | import android.graphics.BitmapFactory
5 | import android.support.v7.app.AppCompatActivity
6 | import android.os.Bundle
7 | import com.glumes.androidcppsolib.R
8 | import com.glumes.cppso.jnioperations.BitmapOps
9 | import com.glumes.cppso.utils.LogUtil
10 | import kotlinx.android.synthetic.main.activity_bitmap_operation.*
11 |
12 | class BitmapOperationActivity : AppCompatActivity() {
13 |
14 |
15 | private val mBitmapOps = BitmapOps()
16 | lateinit var mBitmap: Bitmap
17 | override fun onCreate(savedInstanceState: Bundle?) {
18 | super.onCreate(savedInstanceState)
19 | setContentView(R.layout.activity_bitmap_operation)
20 |
21 | initBitmap()
22 |
23 | // 顺时针旋转 90° 的操作
24 | rotate.setOnClickListener { rotateBitmap(mBitmap) }
25 | // 上下翻转的操作
26 | convert.setOnClickListener { convertBitmap(mBitmap) }
27 | // 左右对调的操作
28 | mirror.setOnClickListener { mirrorBitmap(mBitmap) }
29 | }
30 |
31 | private fun initBitmap() {
32 | mBitmap = BitmapFactory.decodeResource(resources, R.drawable.avatar)
33 | }
34 |
35 | private fun rotateBitmap(bitmap: Bitmap) {
36 | val result = mBitmapOps.rotateBitmap(bitmap)
37 | updateBitmap(result)
38 | }
39 |
40 | private fun convertBitmap(bitmap: Bitmap) {
41 | val result = mBitmapOps.convertBitmap(bitmap)
42 | updateBitmap(result)
43 | }
44 |
45 | private fun mirrorBitmap(bitmap: Bitmap) {
46 | val result = mBitmapOps.mirrorBitmap(bitmap)
47 | updateBitmap(result)
48 | }
49 |
50 | private fun updateBitmap(bitmap: Bitmap?) {
51 | if (bitmap == null) {
52 | LogUtil.e("operation failed")
53 | }
54 | resultView.setImageBitmap(bitmap)
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/InfoManageActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 | import android.os.Bundle
4 | import android.support.design.widget.FloatingActionButton
5 | import android.support.v7.app.AppCompatActivity
6 | import android.support.v7.widget.LinearLayoutManager
7 | import android.support.v7.widget.RecyclerView
8 | import android.view.LayoutInflater
9 | import android.view.View
10 | import com.glumes.androidcppsolib.R
11 | import com.glumes.androidcppsolib.base.BaseListActivity
12 | import com.glumes.androidcppsolib.binder.InfoManagerBinder
13 | import com.glumes.androidcppsolib.binder.SampleBinder
14 | import com.glumes.androidcppsolib.binder.SampleModel
15 | import com.glumes.androidcppsolib.binder.Student
16 | import com.glumes.cppso.infomanager.StudentInfoLoader
17 | import com.glumes.cppso.utils.*
18 | import com.glumes.databindingadapter.DataBindingAdapter
19 | import com.glumes.databindingadapter.Items
20 |
21 | class InfoManageActivity : BaseListActivity(), View.OnClickListener {
22 |
23 |
24 | private var mItems = Items()
25 |
26 | lateinit var mPlus: FloatingActionButton
27 | lateinit var mMinus: FloatingActionButton
28 |
29 | override fun onCreate(savedInstanceState: Bundle?) {
30 | super.onCreate(savedInstanceState)
31 | initData()
32 | mPlus = findViewById(R.id.plus)
33 | mMinus = findViewById(R.id.minus)
34 | mPlus.setOnClickListener(this)
35 | mMinus.setOnClickListener(this)
36 | }
37 |
38 | private fun initData() {
39 | mItems.add(Student("name", 1, "male", 12, 12, R.drawable.woman_16))
40 | loadData()
41 | }
42 |
43 | override fun getLayoutId(): Int {
44 | return R.layout.activity_info_manager
45 | }
46 |
47 | override fun initAdapter(): RecyclerView.Adapter {
48 | val mAdapter = DataBindingAdapter()
49 |
50 | mAdapter
51 | .map(SampleModel::class.java, SampleBinder())
52 | .map(Student::class.java, InfoManagerBinder())
53 | .setItems(mItems)
54 |
55 | return mAdapter
56 | }
57 |
58 | override fun onClick(v: View) {
59 | when (v.id) {
60 | R.id.minus -> {
61 | minusData()
62 | }
63 | R.id.plus -> {
64 | plusData()
65 | }
66 | }
67 | }
68 |
69 | companion object {
70 | init {
71 | System.loadLibrary("info-manger")
72 | }
73 | }
74 |
75 | private external fun loadData()
76 |
77 | private external fun plusData()
78 |
79 | private external fun minusData()
80 | }
81 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/activity/JNIMethodActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.activity
2 |
3 |
4 | import android.graphics.Color
5 | import android.os.Bundle
6 | import android.support.v7.widget.RecyclerView
7 | import android.support.v7.widget.Toolbar
8 | import com.glumes.androidcppsolib.base.BaseListActivity
9 | import com.glumes.androidcppsolib.binder.SampleBinder
10 | import com.glumes.androidcppsolib.binder.SampleModel
11 | import com.glumes.cppso.utils.*
12 | import com.glumes.databindingadapter.DataBindingAdapter
13 | import com.glumes.databindingadapter.Items
14 |
15 | class JNIMethodActivity : BaseListActivity() {
16 |
17 |
18 | private val items = Items()
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | initData()
23 | }
24 |
25 | override fun setUpToolbar(toolbar: Toolbar) {
26 | toolbar.title = "JNI 方法调用"
27 | }
28 |
29 | private fun initData() {
30 | items.add(SampleModel("JNI 动态注册", NATIVE_ON_LOAD))
31 | items.add(SampleModel("JNI 基础类型操作", NATIVE_BASIC_TYPE))
32 | items.add(SampleModel("JNI String 操作", NATIVE_STRING))
33 | items.add(SampleModel("JNI 数组操作", NATIVE_ARRAY))
34 | items.add(SampleModel("JNI 访问 Java 字段和方法", NATIVE_FIELD_AND_METHOD))
35 | items.add(SampleModel("JNI 调用构造方法", NATIVE_INVOKE_CONSTRUCTORS))
36 | items.add(SampleModel("JNI 缓存字段和方法", NATIVE_CACHE_FIELD_AND_METHOD))
37 | items.add(SampleModel("JNI 不同引用类型管理", NATIVE_LOCAL_AND_GLOBAL_REFERENCES))
38 | items.add(SampleModel("JNI 异常处理", NATIVE_EXCEPTIONS_OPERATIONS))
39 | items.add(SampleModel("JNI 线程操作", NATIVE_THREAD_OPS))
40 | }
41 |
42 | override fun initAdapter(): RecyclerView.Adapter {
43 |
44 | val mAdapter = DataBindingAdapter()
45 |
46 | mAdapter.map(SampleModel::class.java, SampleBinder()).setItems(items)
47 |
48 | return mAdapter
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/base/BaseListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.base
2 |
3 | import android.graphics.Color
4 | import android.os.Bundle
5 | import android.support.annotation.LayoutRes
6 | import android.support.v7.widget.LinearLayoutManager
7 | import android.support.v7.widget.RecyclerView
8 | import android.support.v7.widget.Toolbar
9 | import com.glumes.androidcppsolib.R
10 | import com.glumes.sampleutil.BaseToolbarActivity
11 |
12 | /**
13 | * Created by glumes on 28/02/2018
14 | */
15 | abstract class BaseListActivity : BaseToolbarActivity() {
16 |
17 |
18 | lateinit var mRecyclerView: RecyclerView
19 |
20 | override fun onCreate(savedInstanceState: Bundle?) {
21 | super.onCreate(savedInstanceState)
22 | setContentView(getLayoutId())
23 |
24 | mRecyclerView = findViewById(R.id.mRecyclerView)
25 |
26 | initRecyclerView()
27 | }
28 |
29 | @LayoutRes
30 | open fun getLayoutId(): Int {
31 | return R.layout.activity_base_list
32 | }
33 |
34 | fun initRecyclerView() {
35 | val layoutManager = LinearLayoutManager(this)
36 | layoutManager.orientation = LinearLayoutManager.VERTICAL
37 | mRecyclerView.layoutManager = layoutManager
38 | mRecyclerView.setHasFixedSize(true)
39 |
40 | mRecyclerView.adapter = initAdapter()
41 | }
42 |
43 | abstract fun initAdapter(): RecyclerView.Adapter
44 |
45 | override fun setUpToolbar(toolbar: Toolbar) {
46 | toolbar.title = getString(R.string.app_name)
47 | toolbar.setTitleTextColor(Color.WHITE)
48 | }
49 |
50 |
51 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/binder/InfoManagerBinder.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.binder
2 |
3 | import android.databinding.DataBindingUtil
4 | import android.view.LayoutInflater
5 | import android.view.ViewGroup
6 | import com.glumes.androidcppsolib.R
7 | import com.glumes.androidcppsolib.databinding.InfoCardBinding
8 | import com.glumes.databindingadapter.BindingViewHolder
9 | import com.glumes.databindingadapter.ViewHolderBinder
10 |
11 | /**
12 | * Created by glumes on 26/03/2018
13 | */
14 |
15 | data class Student(var name: String, var age: Int, var sex: String, var grade: Int, var stuId: Int, var avatarId: Int)
16 |
17 | class InfoManagerViewHolder(binding: InfoCardBinding) : BindingViewHolder(binding) {
18 |
19 | override fun onBind(data: Student?, position: Int) {
20 | mBinding.model = data
21 | mBinding.executePendingBindings()
22 | }
23 | }
24 |
25 | class InfoManagerBinder : ViewHolderBinder() {
26 |
27 | override fun onBindViewHolder(holder: InfoManagerViewHolder?, data: Student?, position: Int) {
28 | holder!!.onBind(data, position)
29 | }
30 |
31 | override fun createViewHolder(inflater: LayoutInflater?, parent: ViewGroup?): InfoManagerViewHolder {
32 | val mBindind = DataBindingUtil.inflate(inflater!!, R.layout.info_card, parent, false)
33 | return InfoManagerViewHolder(mBindind)
34 | }
35 |
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/binder/JNIMethodBinder.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.binder
2 |
3 | import android.databinding.DataBindingUtil
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import com.glumes.androidcppsolib.R
8 | import com.glumes.androidcppsolib.databinding.ItemJniMethodBinding
9 | import com.glumes.androidcppsolib.handler.JNIOperationHandler
10 | import com.glumes.cppso.utils.NO_NATIVE_OPERATION
11 | import com.glumes.databindingadapter.BindingViewHolder
12 | import com.glumes.databindingadapter.ViewHolderBinder
13 |
14 | /**
15 | * Created by glumes on 28/02/2018
16 | */
17 | data class SampleModel(var content: String, val type: Int = NO_NATIVE_OPERATION)
18 |
19 |
20 | class SampleViewHolder(binding: ItemJniMethodBinding?) : BindingViewHolder(binding) {
21 |
22 | override fun onBind(data: SampleModel?, position: Int) {
23 | mBinding.model = data!!
24 | mBinding.executePendingBindings()
25 | mBinding.eventhandler = NativeEventHandler()
26 | }
27 | }
28 |
29 |
30 | class SampleBinder : ViewHolderBinder() {
31 |
32 | override fun onBindViewHolder(holder: SampleViewHolder?, data: SampleModel?, position: Int) {
33 | holder!!.onBind(data, position)
34 | }
35 |
36 | override fun createViewHolder(inflater: LayoutInflater?, parent: ViewGroup?): SampleViewHolder {
37 | val mBinding = DataBindingUtil.inflate(inflater!!, R.layout.item_jni_method, parent, false) as ItemJniMethodBinding
38 | return SampleViewHolder(mBinding)
39 | }
40 | }
41 |
42 |
43 | class NativeEventHandler {
44 |
45 | fun onClick(view: View, model: SampleModel) {
46 | JNIOperationHandler.handle(model.type)
47 | }
48 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/binder/MainListItemBinder.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.binder
2 |
3 | import android.content.Intent
4 | import android.databinding.DataBindingUtil
5 | import android.view.LayoutInflater
6 | import android.view.View
7 | import android.view.ViewGroup
8 | import com.glumes.androidcppsolib.R
9 | import com.glumes.androidcppsolib.activity.AviBitmapPlayerActivity
10 | import com.glumes.androidcppsolib.activity.BitmapOperationActivity
11 | import com.glumes.androidcppsolib.databinding.ItemMainBinding
12 | import com.glumes.androidcppsolib.activity.InfoManageActivity
13 | import com.glumes.androidcppsolib.activity.JNIMethodActivity
14 | import com.glumes.cppso.utils.JUMP_BITMAP_OPERATION_ACTIVITY
15 | import com.glumes.cppso.utils.JUMP_GRAPHIC_API_ACTIVITY
16 | import com.glumes.cppso.utils.JUMP_INFO_MANAGER_ACTIVITY
17 | import com.glumes.cppso.utils.JUMP_JNI_METHOD_ACTIVITY
18 | import com.glumes.databindingadapter.BindingViewHolder
19 | import com.glumes.databindingadapter.ViewHolderBinder
20 |
21 | /**
22 | * Created by glumes on 26/03/2018
23 | */
24 |
25 | data class MainItem(var title: String, var type: Int)
26 |
27 | class MainViewHolder(binding: ItemMainBinding) : BindingViewHolder(binding) {
28 |
29 | override fun onBind(data: MainItem?, position: Int) {
30 | mBinding.model = data!!
31 | mBinding.executePendingBindings()
32 | mBinding.eventhandler = MainEventHandler()
33 | }
34 |
35 | }
36 |
37 |
38 | class MainListItemBinder : ViewHolderBinder() {
39 |
40 | override fun onBindViewHolder(holder: MainViewHolder?, data: MainItem?, position: Int) {
41 | holder!!.onBind(data, position)
42 | }
43 |
44 | override fun createViewHolder(inflater: LayoutInflater?, parent: ViewGroup?): MainViewHolder {
45 | val mBinding = DataBindingUtil.inflate(inflater!!, R.layout.item_main, parent, false) as ItemMainBinding
46 | return MainViewHolder(mBinding)
47 | }
48 |
49 | }
50 |
51 |
52 | class MainEventHandler {
53 |
54 | fun onClick(view: View, model: MainItem) {
55 | when (model.type) {
56 | JUMP_JNI_METHOD_ACTIVITY -> {
57 | view.context.startActivity(Intent(view.context, JNIMethodActivity::class.java))
58 | }
59 |
60 | JUMP_INFO_MANAGER_ACTIVITY -> {
61 | view.context.startActivity(Intent(view.context, InfoManageActivity::class.java))
62 | }
63 |
64 | JUMP_GRAPHIC_API_ACTIVITY -> {
65 | view.context.startActivity(Intent(view.context, AviBitmapPlayerActivity::class.java))
66 | }
67 |
68 | JUMP_BITMAP_OPERATION_ACTIVITY -> {
69 | view.context.startActivity(Intent(view.context, BitmapOperationActivity::class.java))
70 | }
71 | }
72 | }
73 |
74 | }
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/handler/JNIOperationHandler.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.handler
2 |
3 | import com.glumes.cppso.jnioperations.OperationsFactory
4 |
5 | /**
6 | * @Author glumes
7 | */
8 |
9 | class JNIOperationHandler {
10 |
11 | companion object {
12 |
13 | fun handle(type: Int) {
14 |
15 | OperationsFactory.getInstance().getOperations(type).invoke()
16 |
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/utils/DataBindingUtils.java:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.utils;
2 |
3 | import android.content.res.Resources;
4 | import android.databinding.BindingAdapter;
5 | import android.graphics.drawable.Drawable;
6 | import android.widget.ImageView;
7 |
8 | import com.glumes.androidcppsolib.R;
9 |
10 | /**
11 | * @Author glumes
12 | */
13 |
14 | public class DataBindingUtils {
15 |
16 | @BindingAdapter("app:imageDrawableId")
17 | public static void bindImageDrawable(ImageView view, Integer drawableId) {
18 |
19 | try {
20 | Drawable drawable = view.getContext().getResources().getDrawable(drawableId);
21 | view.setImageDrawable(drawable);
22 | } catch (Resources.NotFoundException e) {
23 | view.setImageResource(R.drawable.woman_16);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/widget/CircleImageView.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.widget
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.widget.ImageView
6 |
7 | /**
8 | * @Author glumes
9 | */
10 | class CircleImageView @JvmOverloads constructor(
11 | context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
12 | ) : ImageView(context, attrs, defStyleAttr) {
13 |
14 |
15 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/glumes/androidcppsolib/widget/ItemInfo.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib.widget
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.widget.LinearLayout
6 |
7 | /**
8 | * @Author glumes
9 | */
10 | class ItemInfo @JvmOverloads constructor(
11 | context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
12 | ) : LinearLayout(context, attrs, defStyleAttr) {
13 |
14 | init {
15 |
16 | }
17 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/drawable/avatar.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/info_card_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
9 |
10 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/info_item_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/material_flat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/drawable/material_flat.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/drawable/minus.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/drawable/plus.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/woman_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/drawable/woman_16.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_avi_open_glplayer.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_avi_player.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_base_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_bitmap_operation.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
26 |
27 |
33 |
34 |
44 |
45 |
56 |
57 |
66 |
67 |
76 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_info_manager.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
16 |
26 |
27 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/info_card.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
14 |
18 |
19 |
26 |
27 |
28 |
33 |
34 |
35 |
42 |
43 |
44 |
54 |
55 |
56 |
62 |
63 |
72 |
73 |
80 |
81 |
82 |
83 |
92 |
93 |
94 |
100 |
101 |
110 |
111 |
118 |
119 |
120 |
121 |
131 |
132 |
133 |
139 |
140 |
150 |
151 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_jni_method.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
16 |
24 |
25 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
16 |
24 |
25 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glumes/AndroidDevWithCpp/1223713cf634ad9e515641aba3245c284f205bc7/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 30dp
4 | 12sp
5 |
6 | 80dp
7 | 40dp
8 |
9 | 329dp
10 | 154dp
11 |
12 | 106dp
13 | 106dp
14 |
15 | 45dp
16 | 21dp
17 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | JNI & NDK 开发实践
3 |
4 | 姓名:
5 | 姓名
6 |
7 | 班级:
8 | 班级
9 |
10 | 学号:
11 | 学号
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/test/java/com/glumes/androidcppsolib/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.glumes.androidcppsolib;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.2.21'
5 | repositories {
6 | jcenter()
7 | google()
8 |
9 | }
10 | dependencies {
11 |
12 | classpath 'com.android.tools.build:gradle:3.1.3'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
17 | }
18 | }
19 |
20 | allprojects {
21 | repositories {
22 | jcenter()
23 | google()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
--------------------------------------------------------------------------------
/cppso/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/cppso/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 |
5 | android {
6 | compileSdkVersion 26
7 |
8 | defaultConfig {
9 | minSdkVersion 22
10 | targetSdkVersion 26
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
15 |
16 | externalNativeBuild {
17 | cmake {
18 | cppFlags "-std=c++11"
19 | }
20 | }
21 |
22 | ndk {
23 | abiFilters 'arm64-v8a', 'x86', 'x86_64', 'armeabi-v7a'
24 | }
25 | }
26 |
27 | buildTypes {
28 | release {
29 | minifyEnabled false
30 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
31 | }
32 | }
33 |
34 | externalNativeBuild {
35 | cmake {
36 | path "src/main/cpp/CMakeLists.txt"
37 | }
38 | }
39 |
40 |
41 |
42 | }
43 |
44 | dependencies {
45 | implementation fileTree(dir: 'libs', include: ['*.jar'])
46 |
47 | implementation 'com.android.support:appcompat-v7:26.1.0'
48 | testImplementation 'junit:junit:4.12'
49 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
50 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
51 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
52 |
53 |
54 | }
55 |
56 |
57 |
--------------------------------------------------------------------------------
/cppso/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/cppso/src/androidTest/java/com/glumes/cppso/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumented test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.glumes.cppso.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/cppso/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html
3 |
4 | # Sets the minimum version of CMake required to build the native library.
5 |
6 | cmake_minimum_required(VERSION 3.4.1)
7 |
8 | # Creates and names a library, sets it as either STATIC
9 | # or SHARED, and provides the relative paths to its source code.
10 | # You can define multiple libraries, and CMake builds them for you.
11 | # Gradle automatically packages shared libraries with your APK.
12 |
13 |
14 | add_library(
15 |
16 | native-operation
17 |
18 | SHARED
19 |
20 | #${CMAKE_SOURCE_DIR}/common/commonutil.cpp
21 | ${CMAKE_SOURCE_DIR}/jnioperations/basic-type-operation.cpp
22 | ${CMAKE_SOURCE_DIR}/jnioperations/string-type-operation.cpp
23 | ${CMAKE_SOURCE_DIR}/jnioperations/array-type-operation.cpp
24 | ${CMAKE_SOURCE_DIR}/jnioperations/filed_and_method_operation.cpp
25 | ${CMAKE_SOURCE_DIR}/jnioperations/cache_filed_and_method.cpp
26 | ${CMAKE_SOURCE_DIR}/jnioperations/invoke_constructor.cpp
27 | ${CMAKE_SOURCE_DIR}/jnioperations/local_and_global_references.cpp
28 | ${CMAKE_SOURCE_DIR}/jnioperations/exceptions-operations.cpp
29 | ${CMAKE_SOURCE_DIR}/jnioperations/native_onload.cpp
30 | ${CMAKE_SOURCE_DIR}/jnioperations/thread_operation.cpp
31 | ${CMAKE_SOURCE_DIR}/jnioperations/bitmap_operation.cpp
32 | )
33 |
34 |
35 |
36 | add_library(
37 | info-manger
38 | SHARED
39 | ${CMAKE_SOURCE_DIR}/jnioperations/basic-type-operation.cpp
40 | ${CMAKE_SOURCE_DIR}/infomanager/LoadManager.cpp
41 | )
42 |
43 |
44 | add_library(
45 | avilib
46 | SHARED
47 | ${CMAKE_SOURCE_DIR}/avilib/avilib.c
48 | ${CMAKE_SOURCE_DIR}/avilib/platform_posix.c
49 | )
50 |
51 |
52 | add_library(
53 | common
54 | SHARED
55 | ${CMAKE_SOURCE_DIR}/common/commonutil.cpp
56 | )
57 |
58 |
59 | add_library(
60 |
61 | aviplayer
62 |
63 | SHARED
64 | ${CMAKE_SOURCE_DIR}/aviplayer/AviPlayer.cpp
65 | ${CMAKE_SOURCE_DIR}/common/commonutil.cpp
66 | )
67 |
68 | include_directories(${CMAKE_SOURCE_DIR}/common/)
69 | include_directories(${CMAKE_SOURCE_DIR}/avilib/)
70 |
71 | # Searches for a specified prebuilt library and stores the path as a
72 | # variable. Because CMake includes system libraries in the search path by
73 | # default, you only need to specify the name of the public NDK library
74 | # you want to add. CMake verifies that the library exists before
75 | # completing its build.
76 |
77 | find_library( # Sets the name of the path variable.
78 | log-lib
79 |
80 | # Specifies the name of the NDK library that
81 | # you want CMake to locate.
82 | log )
83 |
84 |
85 |
86 |
87 | # Specifies libraries CMake should link to your target library. You
88 | # can link multiple libraries, such as libraries you define in this
89 | # build script, prebuilt third-party libraries, or system libraries.
90 |
91 | target_link_libraries( # Specifies the target library.
92 | native-operation
93 | common
94 | jnigraphics
95 | # Links the target library to the log library
96 | # included in the NDK.
97 | ${log-lib} )
98 |
99 | target_link_libraries( # Specifies the target library.
100 | avilib
101 |
102 | # Links the target library to the log library
103 | # included in the NDK.
104 | ${log-lib} )
105 |
106 | target_link_libraries( # Specifies the target library.
107 | aviplayer
108 | common
109 | # Links the target library to the log library
110 | # included in the NDK.
111 | avilib
112 | jnigraphics
113 | GLESv1_CM
114 | GLESv2
115 | ${log-lib} )
116 |
117 | target_link_libraries( # Specifies the target library.
118 | info-manger
119 |
120 | # Links the target library to the log library
121 | # included in the NDK.
122 | ${log-lib} )
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/platform.h:
--------------------------------------------------------------------------------
1 | /*
2 | * platform.h -- platform utilities wrapper for stream handling libraries
3 | * (avilib, wavilib) in transcode.
4 | * (C) 2007-2010 - Francesco Romani
5 | *
6 | * This software is provided 'as-is', without any express or implied
7 | * warranty. In no event will the authors be held liable for any damages
8 | * arising from the use of this software.
9 | *
10 | * Permission is granted to anyone to use this software for any purpose,
11 | * including commercial applications, and to alter it and redistribute it
12 | * freely, subject to the following restrictions:
13 | *
14 | * 1. The origin of this software must not be misrepresented; you must not
15 | * claim that you wrote the original software. If you use this software
16 | * in a product, an acknowledgment in the product documentation would be
17 | * appreciated but is not required.
18 | * 2. Altered source versions must be plainly marked as such, and must not be
19 | * misrepresented as being the original software.
20 | * 3. This notice may not be removed or altered from any source distribution.
21 | */
22 |
23 | #ifndef PLATFORM_H
24 | #define PLATFORM_H
25 |
26 | #ifdef HAVE_CONFIG_H
27 | #include "config.h"
28 | #endif
29 |
30 | #ifdef OS_DARWIN
31 | #include
32 | #endif
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 |
42 |
43 | /*************************************************************************/
44 | /* POSIX-like I/O handling */
45 | /*************************************************************************/
46 |
47 | int plat_open(const char *pathname, int flags, int mode);
48 | int plat_close(int fd);
49 | ssize_t plat_read(int fd, void *buf, size_t count);
50 | ssize_t plat_write(int fd, const void *buf, size_t count);
51 | int64_t plat_seek(int fd, int64_t offset, int whence);
52 | int plat_ftruncate(int fd, int64_t length);
53 |
54 | /*************************************************************************/
55 | /* libc-like memory handling */
56 | /*************************************************************************/
57 |
58 | void *_plat_malloc(const char *file, int line, size_t size);
59 | void *_plat_zalloc(const char *file, int line, size_t size);
60 | void *_plat_realloc(const char *file, int line, void *ptr, size_t size);
61 | void plat_free(void *ptr);
62 |
63 | #define plat_malloc(size) \
64 | _plat_malloc(__FILE__, __LINE__, size)
65 | #define plat_zalloc(size) \
66 | _plat_zalloc(__FILE__, __LINE__, size)
67 | #define plat_realloc(p,size) \
68 | _plat_realloc(__FILE__, __LINE__, p, size)
69 |
70 | /*************************************************************************/
71 | /* simple logging facility */
72 | /*************************************************************************/
73 |
74 | typedef enum platloglevel_ PlatLogLevel;
75 | enum platloglevel_ {
76 | PLAT_LOG_DEBUG = 0,
77 | PLAT_LOG_INFO,
78 | PLAT_LOG_WARNING,
79 | PLAT_LOG_ERROR,
80 | };
81 |
82 | int plat_log_open(void);
83 | int plat_log_send(PlatLogLevel level,
84 | const char *tag, const char *fmt, ...);
85 | int plat_log_close(void);
86 |
87 | #endif /* PLATFORM_H */
88 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/platform_posix.c:
--------------------------------------------------------------------------------
1 | /*
2 | * platform_posix.c -- plain POSIX platform wrappers.
3 | * (C) 2007-2010 - Francesco Romani
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | *
9 | * Permission is granted to anyone to use this software for any purpose,
10 | * including commercial applications, and to alter it and redistribute it
11 | * freely, subject to the following restrictions:
12 | *
13 | * 1. The origin of this software must not be misrepresented; you must not
14 | * claim that you wrote the original software. If you use this software
15 | * in a product, an acknowledgment in the product documentation would be
16 | * appreciated but is not required.
17 | * 2. Altered source versions must be plainly marked as such, and must not be
18 | * misrepresented as being the original software.
19 | * 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | #include "platform.h"
23 |
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | /*************************************************************************/
30 | /* I/O is straightforward. */
31 | /*************************************************************************/
32 |
33 | int plat_open(const char *pathname, int flags, int mode)
34 | {
35 | return open(pathname, flags, mode);
36 | }
37 |
38 | int plat_close(int fd)
39 | {
40 | return close(fd);
41 | }
42 |
43 | /*
44 | * automatically restart after a recoverable interruption
45 | */
46 | ssize_t plat_read(int fd, void *buf, size_t count)
47 | {
48 | ssize_t n = 0, r = 0;
49 |
50 | while (r < count) {
51 | n = read(fd, buf + r, count - r);
52 | if (n == 0)
53 | break;
54 | if (n < 0) {
55 | if (errno == EINTR)
56 | continue;
57 | else
58 | break;
59 | }
60 |
61 | r += n;
62 | }
63 | return r;
64 | }
65 |
66 | /*
67 | * automatically restart after a recoverable interruption
68 | */
69 | ssize_t plat_write(int fd, const void *buf, size_t count)
70 | {
71 | ssize_t n = 0, r = 0;
72 |
73 | while (r < count) {
74 | n = write(fd, buf + r, count - r);
75 | if (n < 0)
76 | return n;
77 |
78 | r += n;
79 | }
80 | return r;
81 | }
82 |
83 |
84 | int64_t plat_seek(int fd, int64_t offset, int whence)
85 | {
86 | return lseek(fd, offset, whence);
87 | }
88 |
89 | int plat_ftruncate(int fd, int64_t length)
90 | {
91 | return ftruncate(fd, length);
92 | }
93 |
94 |
95 |
96 | /*************************************************************************/
97 | /* Memory management is straightforward too. */
98 | /*************************************************************************/
99 |
100 | void *_plat_malloc(const char *file, int line, size_t size)
101 | {
102 | return malloc(size);
103 | }
104 |
105 | void *_plat_zalloc(const char *file, int line, size_t size)
106 | {
107 | return calloc(1, size);
108 | }
109 |
110 | void *_plat_realloc(const char *file, int line, void *ptr, size_t size)
111 | {
112 | return realloc(ptr, size);
113 | }
114 |
115 | void plat_free(void *ptr)
116 | {
117 | free(ptr);
118 | }
119 |
120 |
121 |
122 | /*************************************************************************/
123 | /* Trivial logging support. */
124 | /*************************************************************************/
125 |
126 | int plat_log_open(void)
127 | {
128 | return 0;
129 | }
130 |
131 | int plat_log_send(PlatLogLevel level,
132 | const char *tag, const char *fmt, ...)
133 | {
134 | char buffer[1024];
135 | va_list ap;
136 |
137 | va_start(ap, fmt);
138 | vsnprintf(buffer, 1024, fmt, ap);
139 | va_end(ap);
140 |
141 | fprintf(stderr, "[%s] %s\n", tag, buffer);
142 |
143 | return 0;
144 | }
145 |
146 | int plat_log_close(void)
147 | {
148 | return 0;
149 | }
150 |
151 | // EOF
152 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/platform_tc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * platform_tc.c -- platform wrapper over libtc functions.
3 | * (C) 2007-2010 - Francesco Romani
4 | *
5 | * This file is part of transcode, a video stream processing tool.
6 | *
7 | * transcode is free software; you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation; either version 2 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * transcode is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 |
21 |
22 | #include "platform.h"
23 |
24 | #include "libtc/xio.h"
25 | #include "libtc/libtc.h"
26 |
27 | #include
28 | #include
29 | #include
30 |
31 |
32 | int plat_open(const char *pathname, int flags, int mode)
33 | {
34 | return xio_open(pathname, flags, mode);
35 | }
36 |
37 | int plat_close(int fd)
38 | {
39 | return xio_close(fd);
40 | }
41 |
42 | ssize_t plat_read(int fd, void *buf, size_t count)
43 | {
44 | return tc_pread(fd, buf, count);
45 | }
46 |
47 | ssize_t plat_write(int fd, const void *buf, size_t count)
48 | {
49 | return tc_pwrite(fd, buf, count);
50 | }
51 |
52 | int64_t plat_seek(int fd, int64_t offset, int whence)
53 | {
54 | return xio_lseek(fd, offset, whence);
55 | }
56 |
57 | int plat_ftruncate(int fd, int64_t length)
58 | {
59 | return xio_ftruncate(fd, length);
60 | }
61 |
62 |
63 |
64 | void *_plat_malloc(const char *file, int line, size_t size)
65 | {
66 | return _tc_malloc(file, line, size);
67 | }
68 |
69 | void *_plat_zalloc(const char *file, int line, size_t size)
70 | {
71 | return _tc_zalloc(file, line, size);
72 | }
73 |
74 | void *_plat_realloc(const char *file, int line, void *ptr, size_t size)
75 | {
76 | return _tc_realloc(file, line, ptr, size);
77 | }
78 |
79 | void plat_free(void *ptr)
80 | {
81 | return tc_free(ptr);
82 | }
83 |
84 |
85 |
86 | int plat_log_open(void)
87 | {
88 | return 0;
89 | }
90 |
91 | int plat_log_send(PlatLogLevel level,
92 | const char *tag, const char *fmt, ...)
93 | {
94 | static const TCLogLevel trans_tab[] = {
95 | TC_LOG_MSG, /* PLAT_LOG_DEBUG */
96 | TC_LOG_INFO, /* PLAT_LOG_INFO */
97 | TC_LOG_WARN, /* PLAT_LOG_WARNING */
98 | TC_LOG_ERR, /* PLAT_LOG_ERROR */
99 | };
100 | char buffer[TC_BUF_MAX];
101 | va_list ap;
102 |
103 | va_start(ap, fmt);
104 | tc_vsnprintf(buffer, TC_BUF_MAX, fmt, ap);
105 | va_end(ap);
106 |
107 | return tc_log(trans_tab[level], tag, "%s", buffer);
108 | }
109 |
110 | int plat_log_close(void)
111 | {
112 | return 0;
113 | }
114 |
115 | // EOF
116 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/static_avilib.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _STATIC_AVILIB_H_
3 | #define _STATIC_AVILIB_H_
4 |
5 | #include "avilib/avilib.h"
6 | void dummy_avilib(void);
7 | void dummy_avilib(void) {
8 | avi_t *infile = NULL;
9 | avi_t *outfile = NULL;
10 | infile = AVI_open_input_file((char *)NULL, 1);
11 | outfile = AVI_open_output_file((char *)NULL);
12 | AVI_set_audio_track(outfile, 0);
13 | AVI_set_audio(outfile, 0, 0, 0, 0, 0);
14 | AVI_set_audio_vbr(outfile, 0);
15 | AVI_set_video(outfile, 0, 0, 0.0, NULL);
16 | AVI_dump((char *)NULL, 0);
17 | AVI_write_frame(outfile, NULL, 0, 0);
18 | AVI_write_audio(outfile, NULL, 0);
19 | AVI_bytes_written(outfile);
20 | AVI_max_size();
21 | AVI_strerror();
22 | AVI_close(infile);
23 | AVI_close(outfile);
24 | }
25 |
26 | #endif // _STATIC_AVILIB_H_
27 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/static_wavlib.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef _STATIC_WAVLIB_H_
3 | #define _STATIC_WAVLIB_H_
4 |
5 | #include "avilib/wavlib.h"
6 | void dummy_wavlib(void);
7 | void dummy_wavlib(void) {
8 | WAV wav = NULL;
9 | WAVError err;
10 |
11 | wav = wav_open(NULL, WAV_READ, &err);
12 | wav_close(wav);
13 | }
14 |
15 | #endif // _STATIC_WAVLIB_H_
16 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/wavlib.c:
--------------------------------------------------------------------------------
1 | /*
2 | * wavlib.c - simple WAV I/O library interface
3 | * Copyright (C) 2006-2010 Francesco Romani
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | *
9 | * Permission is granted to anyone to use this software for any purpose,
10 | * including commercial applications, and to alter it and redistribute it
11 | * freely, subject to the following restrictions:
12 | *
13 | * 1. The origin of this software must not be misrepresented; you must not
14 | * claim that you wrote the original software. If you use this software
15 | * in a product, an acknowledgment in the product documentation would be
16 | * appreciated but is not required.
17 | * 2. Altered source versions must be plainly marked as such, and must not be
18 | * misrepresented as being the original software.
19 | * 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | #include "wavlib.h"
23 | #include "platform.h"
24 |
25 | #include
26 | #include
27 | #include
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | /*************************************************************************
34 | * utilties *
35 | *************************************************************************/
36 |
37 | #define WAV_BUF_SIZE (1024)
38 |
39 | #if (!defined HAVE_BYTESWAP && defined WAV_BIG_ENDIAN)
40 |
41 | static uint16_t bswap_16(uint16_t x)
42 | {
43 | return (((x & 0xff00) >> 8) | ((x & 0x00ff) << 8));
44 | }
45 |
46 | static uint32_t bswap_32(uint32_t x)
47 | {
48 | return (((x & 0xff000000UL) >> 24) |
49 | ((x & 0x00ff0000UL) >> 8) |
50 | ((x & 0x0000ff00UL) << 8) |
51 | ((x & 0x000000ffUL) << 24));
52 | }
53 |
54 | static uint64_t bswap_64(uint64_t x)
55 | {
56 | return (((x & 0xff00000000000000ULL) >> 56) |
57 | ((x & 0x00ff000000000000ULL) >> 40) |
58 | ((x & 0x0000ff0000000000ULL) >> 24) |
59 | ((x & 0x000000ff00000000ULL) >> 8) |
60 | ((x & 0x00000000ff000000ULL) << 8) |
61 | ((x & 0x0000000000ff0000ULL) << 24) |
62 | ((x & 0x000000000000ff00ULL) << 40) |
63 | ((x & 0x00000000000000ffULL) << 56));
64 | }
65 | #endif
66 |
67 | #if (!defined WAV_BIG_ENDIAN && !defined WAV_LITTLE_ENDIAN)
68 | #error "you must define either LITTLE_ENDIAN or BIG_ENDIAN"
69 | #endif
70 |
71 | #if (defined WAV_BIG_ENDIAN && defined WAV_LITTLE_ENDIAN)
72 | #error "you CAN'T define BOTH LITTLE_ENDIAN and BIG_ENDIAN"
73 | #endif
74 |
75 | #if defined WAV_BIG_ENDIAN
76 | #define htol_16(x) bswap_16(x)
77 | #define htol_32(x) bswap_32(x)
78 | #define htol_64(x) bswap_64(x)
79 |
80 | #elif defined WAV_LITTLE_ENDIAN
81 |
82 | #define htol_16(x) (x)
83 | #define htol_32(x) (x)
84 | #define htol_64(x) (x)
85 |
86 | #endif
87 |
88 | /* often used out-of-order */
89 | #define make_wav_get_bits(s) \
90 | static inline uint##s##_t wav_get_bits##s(uint8_t *d) \
91 | { \
92 | return htol_##s(*((uint##s##_t*)d)); \
93 | }
94 |
95 | /* often used sequentially */
96 | #define make_wav_put_bits(s) \
97 | static inline uint8_t *wav_put_bits##s(uint8_t *d, uint##s##_t u) \
98 | { \
99 | *((uint##s##_t*)d) = htol_##s(u); \
100 | return (d + (s / 8)); \
101 | }
102 |
103 | make_wav_get_bits(16)
104 | make_wav_get_bits(32)
105 | make_wav_get_bits(64)
106 |
107 | make_wav_put_bits(16)
108 | make_wav_put_bits(32)
109 | make_wav_put_bits(64)
110 |
111 | static inline uint32_t make_tag(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
112 | {
113 | return (a | (b << 8) | (c << 16) | (d << 24));
114 | }
115 |
116 | /*************************************************************************
117 | * header data *
118 | *************************************************************************/
119 |
120 | /*
121 | * WAVE header:
122 | *
123 | * TAG: 'RIFF' 4 bytes
124 | * LENGTH: 4 bytes
125 | * TAG: 'WAVE' 4 bytes
126 | *
127 | * TAG: 'fmt ' 4 bytes
128 | * LENGTH: 4 bytes
129 | *
130 | * +
131 | * FORMAT: 2 bytes |
132 | * CHANNELS: 2 bytes |
133 | * SAMPLES: 4 bytes | simple WAV format:
134 | * AVGBYTES: 4 bytes | 16 byte
135 | * BLKALIGN: 2 bytes |
136 | * BITS: 2 bytes |
137 | * +
138 | *
139 | * TAG: 'data' 4 bytes
140 | * LENGTH: 4 bytes
141 | *
142 | * ----------------------------
143 | * TOTAL wav header: 44 bytes
144 | */
145 |
146 | #define WAV_HEADER_LEN (44)
147 | #define WAV_FORMAT_LEN (16)
148 |
149 | #define PCM_ID (0x1)
150 |
151 | /*************************************************************************
152 | * core data/routines *
153 | *************************************************************************/
154 |
155 | #define WAV_SET_ERROR(errp, code) \
156 | if (errp != NULL) { \
157 | *errp = code; \
158 | }
159 |
160 | struct wav_ {
161 | int fd;
162 |
163 | int header_done;
164 | int close_fd;
165 | int has_pipe;
166 |
167 | WAVMode mode;
168 | WAVError error;
169 |
170 | uint32_t len;
171 |
172 | uint32_t bitrate;
173 | uint16_t bits;
174 | uint16_t channels;
175 | uint32_t rate;
176 |
177 | uint16_t block_align;
178 | };
179 |
180 | const char *wav_strerror(WAVError err)
181 | {
182 | const char *s = NULL;
183 |
184 | switch (err) {
185 | case WAV_SUCCESS:
186 | s = "no error";
187 | break;
188 | case WAV_NO_MEM:
189 | s = "can't acquire the needed amount of memory";
190 | break;
191 | case WAV_IO_ERROR:
192 | s = "error while performing I/O operation";
193 | break;
194 | case WAV_BAD_FORMAT:
195 | s = "incorrect/unrecognized WAV data";
196 | break;
197 | case WAV_BAD_PARAM:
198 | s = "bad/unknown parameter for this operation";
199 | break;
200 | case WAV_UNSUPPORTED:
201 | s = "not yet supported by wavlib";
202 | break;
203 | default:
204 | s = NULL;
205 | break;
206 | }
207 | return s;
208 | }
209 |
210 | static int wav_parse_header(WAV handle, WAVError *err)
211 | {
212 | uint8_t hdr[WAV_HEADER_LEN];
213 | ssize_t r = 0;
214 | uint16_t wav_fmt = 0;
215 | uint32_t fmt_len = 0;
216 |
217 | if (!handle || handle->fd == -1 || !(handle->mode & WAV_READ)) {
218 | return -1;
219 | }
220 |
221 | r = plat_read(handle->fd, hdr, WAV_HEADER_LEN);
222 | if (r != WAV_HEADER_LEN) {
223 | WAV_SET_ERROR(err, WAV_BAD_FORMAT);
224 | goto bad_wav;
225 | }
226 | if ((wav_get_bits32(hdr) != make_tag('R', 'I', 'F', 'F'))
227 | || (wav_get_bits32(hdr + 8) != make_tag('W', 'A', 'V', 'E'))
228 | || (wav_get_bits32(hdr + 12) != make_tag('f', 'm', 't', ' '))) {
229 | WAV_SET_ERROR(err, WAV_BAD_FORMAT);
230 | goto bad_wav;
231 | }
232 |
233 | fmt_len = wav_get_bits32(hdr + 16);
234 | wav_fmt = wav_get_bits16(hdr + 20);
235 | if (fmt_len != WAV_FORMAT_LEN || wav_fmt != PCM_ID) {
236 | WAV_SET_ERROR(err, WAV_UNSUPPORTED);
237 | goto bad_wav;
238 | }
239 |
240 | handle->len = wav_get_bits32(hdr + 4);
241 | handle->channels = wav_get_bits16(hdr + 22);
242 | handle->rate = wav_get_bits32(hdr + 24);
243 | handle->bitrate = (wav_get_bits32(hdr + 28) * 8) / 1000;
244 | handle->block_align = wav_get_bits16(hdr + 32);
245 | handle->bits = wav_get_bits16(hdr + 34);
246 | /* skip 'data' tag (4 bytes) */
247 | handle->len = wav_get_bits32(hdr + 40);
248 |
249 | return 0;
250 |
251 | bad_wav:
252 | lseek(handle->fd, 0, SEEK_SET);
253 | return 1;
254 | }
255 |
256 | int wav_write_header(WAV handle, int force)
257 | {
258 | uint8_t hdr[WAV_HEADER_LEN];
259 | uint8_t *ph = hdr;
260 | off_t pos = 0, ret = 0;
261 | ssize_t w = 0;
262 |
263 | if (!handle) {
264 | return -1;
265 | }
266 | if (!force && handle->header_done) {
267 | return 0;
268 | }
269 | if (handle->bits != 0
270 | && (handle->bits != 8 && handle->bits != 16)) {
271 | /* bits == 0 -> not specified (so it's good) */
272 | WAV_SET_ERROR(&(handle->error), WAV_UNSUPPORTED);
273 | return -1;
274 | }
275 |
276 | if (!handle->has_pipe) {
277 | pos = lseek(handle->fd, 0, SEEK_CUR);
278 | ret = lseek(handle->fd, 0, SEEK_SET);
279 | if (ret == (off_t)-1) {
280 | return 1;
281 | }
282 | }
283 |
284 | ph = wav_put_bits32(ph, make_tag('R', 'I', 'F', 'F'));
285 | ph = wav_put_bits32(ph, handle->len + WAV_HEADER_LEN - 8);
286 | ph = wav_put_bits32(ph, make_tag('W', 'A', 'V', 'E'));
287 |
288 | ph = wav_put_bits32(ph, make_tag('f', 'm', 't', ' '));
289 | ph = wav_put_bits32(ph, WAV_FORMAT_LEN);
290 |
291 | /* format */
292 | ph = wav_put_bits16(ph, PCM_ID);
293 | /* wave format, only plain PCM supported, yet */
294 | ph = wav_put_bits16(ph, handle->channels);
295 | /* number of channels */
296 | ph = wav_put_bits32(ph, handle->rate);
297 | /* sample rate */
298 | ph = wav_put_bits32(ph, (handle->bitrate * 1000)/8);
299 | /* average bytes per second (aka bitrate) */
300 | ph = wav_put_bits16(ph, ((handle->channels * handle->bits) / 8));
301 | /* block alignment */
302 | ph = wav_put_bits16(ph, handle->bits);
303 | /* bits for sample */
304 |
305 | ph = wav_put_bits32(ph, make_tag('d', 'a', 't', 'a'));
306 | ph = wav_put_bits32(ph, handle->len);
307 |
308 | w = plat_write(handle->fd, hdr, WAV_HEADER_LEN);
309 |
310 | if (!handle->has_pipe) {
311 | ret = lseek(handle->fd, pos, SEEK_CUR);
312 | if (ret == (off_t)-1) {
313 | return 1;
314 | }
315 | }
316 |
317 | if (w != WAV_HEADER_LEN) {
318 | return 2;
319 | }
320 | handle->header_done = 1;
321 | return 0;
322 | }
323 |
324 | WAV wav_open(const char *filename, WAVMode mode, WAVError *err)
325 | {
326 | int oflags = (mode & WAV_READ) ?O_RDONLY :O_TRUNC|O_CREAT|O_WRONLY;
327 | int fd = -1;
328 | WAV wav = NULL;
329 |
330 | if (!filename || !strlen(filename)) {
331 | WAV_SET_ERROR(err, WAV_BAD_PARAM);
332 | } else {
333 | fd = plat_open(filename, oflags,
334 | S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
335 | wav = wav_fdopen(fd, mode, err);
336 | if (!wav) {
337 | plat_close(fd);
338 | } else {
339 | wav->close_fd = 1;
340 | }
341 | }
342 | return wav;
343 | }
344 |
345 | #define DEL_WAV(wav) do { \
346 | plat_free((wav)); \
347 | (wav) = NULL; \
348 | } while (0)
349 |
350 | WAV wav_fdopen(int fd, WAVMode mode, WAVError *err)
351 | {
352 | WAV wav = plat_zalloc(sizeof(struct wav_));
353 |
354 | if (!wav) {
355 | WAV_SET_ERROR(err, WAV_NO_MEM);
356 | } else {
357 | wav->fd = fd;
358 | wav->mode = mode;
359 | wav->close_fd = 0;
360 | wav->has_pipe = (mode & WAV_PIPE) ?1 :0;
361 |
362 | if (mode & WAV_READ) {
363 | if (0 != wav_parse_header(wav, err)) {
364 | DEL_WAV(wav);
365 | } else {
366 | wav->header_done = 1; /* skip write_header */
367 | }
368 | } else if (mode & WAV_WRITE) {
369 | /* reserve space for header by writing a fake one */
370 | if (!wav->has_pipe && 0 != wav_write_header(wav, 1)) {
371 | WAV_SET_ERROR(err, wav->error);
372 | /* only I/O error */
373 | DEL_WAV(wav);
374 | }
375 | } else {
376 | WAV_SET_ERROR(err, WAV_BAD_PARAM);
377 | DEL_WAV(wav);
378 | }
379 | }
380 | return wav;
381 | }
382 |
383 |
384 | #define RETURN_IF_IOERROR(err) \
385 | if (err != 0) { \
386 | WAV_SET_ERROR(&(handle->error), WAV_IO_ERROR); \
387 | return -1; \
388 | }
389 |
390 | int wav_close(WAV handle)
391 | {
392 | int ret = 0;
393 |
394 | if (!handle) {
395 | return -1;
396 | }
397 |
398 | if (!handle->has_pipe && handle->mode & WAV_WRITE) {
399 | ret = wav_write_header(handle, 1);
400 | RETURN_IF_IOERROR(ret);
401 | }
402 |
403 | if (handle->close_fd) {
404 | ret = plat_close(handle->fd);
405 | RETURN_IF_IOERROR(ret);
406 | }
407 | plat_free(handle);
408 |
409 | return 0;
410 | }
411 |
412 | #undef RETURN_IF_IOERROR
413 |
414 | uint32_t wav_chunk_size(WAV handle, double fps)
415 | {
416 | uint32_t size = 0;
417 | double fch;
418 |
419 | if (!handle || !fps) {
420 | return -1;
421 | }
422 |
423 | fch = handle->rate / fps;
424 |
425 | /* bytes per audio frame */
426 | size = (int)(fch * (handle->bits / 8) * handle->channels);
427 | size = (size>>2)<<2; /* XXX */
428 |
429 | return 0;
430 | }
431 |
432 | WAVError wav_last_error(WAV handle)
433 | {
434 | return (handle) ?(handle->error) :WAV_BAD_PARAM;
435 | }
436 |
437 | uint32_t wav_get_bitrate(WAV handle)
438 | {
439 | return (handle) ?(handle->bitrate) :0;
440 | }
441 |
442 | uint16_t wav_get_rate(WAV handle)
443 | {
444 | return (handle) ?(handle->rate) :0;
445 | }
446 |
447 | uint8_t wav_get_channels(WAV handle)
448 | {
449 | return (handle) ?(handle->channels) :0;
450 | }
451 |
452 | uint8_t wav_get_bits(WAV handle)
453 | {
454 | return (handle) ?(handle->bits) :0;
455 | }
456 |
457 | void wav_set_rate(WAV handle, uint16_t rate)
458 | {
459 | if (handle && handle->mode & WAV_WRITE) {
460 | handle->rate = rate;
461 | }
462 | }
463 |
464 | void wav_set_channels(WAV handle, uint8_t channels)
465 | {
466 | if (handle && handle->mode & WAV_WRITE) {
467 | handle->channels = channels;
468 | }
469 | }
470 |
471 | void wav_set_bits(WAV handle, uint8_t bits)
472 | {
473 | if (handle && handle->mode & WAV_WRITE) {
474 | handle->bits = bits;
475 | }
476 | }
477 |
478 | void wav_set_bitrate(WAV handle, uint32_t bitrate)
479 | {
480 | if (handle && handle->mode & WAV_WRITE) {
481 | handle->bitrate = bitrate;
482 | }
483 | }
484 |
485 | #ifdef WAV_BIG_ENDIAN
486 |
487 | /* assume dlen % 2 == 0 */
488 | static void bswap_buffer(void *data, size_t bytes)
489 | {
490 | size_t i = 0;
491 | uint16_t *ptr = data;
492 |
493 | for (ptr = data, i = 0; i < bytes; ptr++, i += 2) {
494 | *ptr = bswap_16(*ptr);
495 | }
496 | }
497 |
498 | #define SWAP_WRITE_CHUNK(data, len) do { \
499 | memcpy(conv_buf, (data), (len)); \
500 | bswap_buffer(conv_buf, (len)); \
501 | ret = plat_write(fd, conv_buf, (len)); \
502 | } while (0)
503 |
504 | static ssize_t wav_bswap_fdwrite(int fd, const uint8_t *buf, size_t len)
505 | {
506 | uint8_t conv_buf[WAV_BUF_SIZE];
507 | size_t blocks = len / WAV_BUF_SIZE, rest = len % WAV_BUF_SIZE, i = 0;
508 | ssize_t ret = 0, tot = 0;
509 |
510 | for (i = 0; i < blocks; i++) {
511 | SWAP_WRITE_CHUNK(buf + (i * WAV_BUF_SIZE), WAV_BUF_SIZE);
512 | if (ret != WAV_BUF_SIZE) {
513 | break;
514 | }
515 | tot += ret;
516 | }
517 |
518 | SWAP_WRITE_CHUNK(buf + (i * WAV_BUF_SIZE), rest);
519 | return tot + ret;
520 | }
521 |
522 | #undef SWAP_WRITE_CHUNK
523 |
524 | #endif /* WAV_BIG_ENDIAN */
525 |
526 | ssize_t wav_read_data(WAV handle, uint8_t *buffer, size_t bufsize)
527 | {
528 | ssize_t r = 0;
529 |
530 | if (!handle) {
531 | return -1;
532 | }
533 | if (!buffer || bufsize < 0) {
534 | WAV_SET_ERROR(&(handle->error), WAV_BAD_PARAM);
535 | return -1;
536 | }
537 | if (!(handle->mode & WAV_READ) || (bufsize % 2 != 0)) {
538 | WAV_SET_ERROR(&(handle->error), WAV_UNSUPPORTED);
539 | return -1;
540 | }
541 | r = plat_read(handle->fd, buffer, bufsize);
542 |
543 | #ifdef WAV_BIG_ENDIAN
544 | bswap_buffer(buffer, r);
545 | #endif
546 | return r;
547 | }
548 |
549 | ssize_t wav_write_data(WAV handle, const uint8_t *buffer, size_t bufsize)
550 | {
551 | ssize_t w = 0;
552 |
553 | if (!handle) {
554 | return -1;
555 | }
556 | if (!buffer || bufsize < 0) {
557 | WAV_SET_ERROR(&(handle->error), WAV_BAD_PARAM);
558 | return -1;
559 | }
560 | if (!(handle->mode & WAV_WRITE) || (bufsize % 2 != 0)) {
561 | WAV_SET_ERROR(&(handle->error), WAV_UNSUPPORTED);
562 | return -1;
563 | }
564 | if (wav_write_header(handle, 0) != 0) {
565 | return -1;
566 | }
567 | #ifdef WAV_BIG_ENDIAN
568 | w = wav_bswap_fdwrite(handle->fd, buffer, bufsize);
569 | #else
570 | w = plat_write(handle->fd, buffer, bufsize);
571 | #endif
572 | if (w == bufsize) {
573 | handle->len += w;
574 | }
575 | return w;
576 | }
577 |
578 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/avilib/wavlib.h:
--------------------------------------------------------------------------------
1 | /*
2 | * wavlib.h - simple WAV I/O library interface
3 | * Copyright (C) 2006-2010 Francesco Romani
4 | *
5 | * This software is provided 'as-is', without any express or implied
6 | * warranty. In no event will the authors be held liable for any damages
7 | * arising from the use of this software.
8 | *
9 | * Permission is granted to anyone to use this software for any purpose,
10 | * including commercial applications, and to alter it and redistribute it
11 | * freely, subject to the following restrictions:
12 | *
13 | * 1. The origin of this software must not be misrepresented; you must not
14 | * claim that you wrote the original software. If you use this software
15 | * in a product, an acknowledgment in the product documentation would be
16 | * appreciated but is not required.
17 | * 2. Altered source versions must be plainly marked as such, and must not be
18 | * misrepresented as being the original software.
19 | * 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | #ifndef _WAVLIB_H_
23 | #define _WAVLIB_H_
24 |
25 | #ifdef HAVE_CONFIG_H
26 | # include "config.h"
27 | #endif
28 |
29 | #include
30 | #include
31 |
32 | /* transcode build system integration */
33 | #ifdef WORDS_BIGENDIAN
34 | #define WAV_BIG_ENDIAN 1
35 | #else
36 | #define WAV_LITTLE_ENDIAN 1
37 | #endif
38 |
39 | #define WAVLIB_VERSION "0.2.0"
40 | #define WAVLIB_MAJOR 0
41 | #define WAVLIB_MINOR 2
42 | #define WAVLIB_PATCH 0
43 |
44 | typedef enum {
45 | WAV_READ = 1, /* open WAV file in read-only mode */
46 | WAV_WRITE = 2, /* open WAV file in write-only mode */
47 | WAV_PIPE = 4, /* cut SEEEKs */
48 | } WAVMode;
49 |
50 | typedef enum {
51 | WAV_SUCCESS, /* no error so far */
52 | WAV_NO_MEM, /* can't acquire requested amount of memory */
53 | WAV_IO_ERROR, /* unable to read/write (often write) data */
54 | WAV_BAD_FORMAT, /* acquired data doesn't seem wav-compliant */
55 | WAV_BAD_PARAM, /* bad parameter for requested operation */
56 | WAV_UNSUPPORTED, /* feature not yet supported by wavlib */
57 | } WAVError;
58 |
59 | typedef struct wav_ *WAV;
60 |
61 | /*
62 | * wav_open:
63 | * open a WAVE file in given mode, either read-only or write-only,
64 | * and associate a WAV descriptor to it.
65 | *
66 | * Parameters:
67 | * filename: path of WAVE file to open.
68 | * mode: mode to open WAVE file.
69 | * Can be either WAV_READ (open read-only)
70 | * or WAV_WRITE (open write only).
71 | * WAV_PIPE can be OR'd with this parameter if given
72 | * filename is a named pipe. This flag is honoured only
73 | * if mode is WAV_READ.
74 | * err: if not NULL, reason for error, if any, will be stored
75 | * on WAVError pointed by this parameter.
76 | *
77 | * Return Value:
78 | * a valid WAV descriptor if successfull, or NULL otherwise.
79 | * Side effects:
80 | * N/A
81 | * Preconditions:
82 | * N/A
83 | * Postconditions:
84 | * N/A
85 | */
86 | WAV wav_open(const char *filename, WAVMode mode, WAVError *err);
87 |
88 | /*
89 | * wav_fdopen:
90 | * attach a WAV descriptor to already open POSIX file descriptor.
91 | *
92 | * Parameters:
93 | * fd: existing file descriptor; WAV descriptor will be attached here.
94 | * mode: mode to open WAVE file.
95 | * Can be either WAV_READ (open read-only)
96 | * or WAV_WRITE (open write only).
97 | * WAV_PIPE can be OR'd with this parameter if given
98 | * filename is a pipe.
99 | * value of 'mode' MUST be congruent with mode of given
100 | * file descriptor.
101 | * err: if not NULL, reason for error, if any, will be stored
102 | * on WAVError pointed by this parameter.
103 | *
104 | * Return Value:
105 | * a valid WAV descriptor if successfull, or NULL otherwise.
106 | * Side effects:
107 | * N/A
108 | * Preconditions:
109 | * N/A
110 | * Postconditions:
111 | * N/A
112 | */
113 | WAV wav_fdopen(int fd, WAVMode mode, WAVError *err);
114 |
115 | /*
116 | * wav_close:
117 | * close a WAV descriptor, freeing acquired resources,
118 | *
119 | * Parameters:
120 | * handle: WAV descriptor to close
121 | * Return Value:
122 | * 0 if successfull, -1 otherwise
123 | * Side effects:
124 | * if error, error code is stored in WAV descritptor, and
125 | * can be fetched using wav_last_error.
126 | * If WAV descriptor was open using WAV_WRITE mode, WAVE
127 | * header will be updated using wav_write_header.
128 | * Preconditions:
129 | * given wav handle is a valid one obtained as return value of
130 | * wav_open/wav_fdopen.
131 | * Postconditions:
132 | * N/A
133 | */
134 | int wav_close(WAV handle);
135 |
136 | /*
137 | * wav_read_data:
138 | * read a buffer of pcm data from given wav file. Delivers data
139 | * in wav-native-byte-order (little endian).
140 | * This function doesn't mess with given data, it just reads
141 | * data verbatim from wav file. so caller must take care to
142 | * split/join channel data or do any needed operation.
143 | *
144 | * Parameters:
145 | * handle: wav handle to write data in
146 | * buffer: pointer to data to store the data readed
147 | * bufsize: size of given buffer.
148 | * Return Value:
149 | * return of bytes effectively readed from wav file.
150 | * -1 means an error.
151 | * Side effects:
152 | * N/A
153 | * Preconditions:
154 | * given wav handle is a valid one obtained as return value of
155 | * wav_open/wav_fdopen; wav handle was opened in WAV_READ mode.
156 | * bufsize is a multiple of 2.
157 | * Postconditions:
158 | * N/A
159 | */
160 | ssize_t wav_read_data(WAV handle, uint8_t *buffer, size_t bufsize);
161 |
162 | /*
163 | * wav_write_data:
164 | * write a buffer of pcm data in given wav file. Expect data
165 | * in wav-native-byte-order (little endian).
166 | * This function doesn't mess with given data, it just writes
167 | * data verbatim on wav file. so caller must take care to
168 | * split/join channel data or do any needed operation.
169 | *
170 | * Parameters:
171 | * handle: wav handle to write data in
172 | * buffer: pointer to data to be written
173 | * bufsize: number of bytes of data to write
174 | * Return Value:
175 | * return of bytes effectively written on wav file.
176 | * -1 means an error.
177 | * Side effects:
178 | * N/A
179 | * Preconditions:
180 | * given wav handle is a valid one obtained as return value of
181 | * wav_open/wav_fdopen; wav handle was opened in WAV_WRITE mode.
182 | * buffer contains data in wav-native-byte-order (little endian)
183 | * bufsize is a multiple of 2.
184 | * Postconditions:
185 | * N/A
186 | */
187 | ssize_t wav_write_data(WAV handle, const uint8_t *buffer, size_t bufsize);
188 |
189 | /*
190 | * wav_chunk_size:
191 | * guess^Wcompute the appropriate buffer size for reading/writing data
192 | * with given wav descriptor.
193 | *
194 | * Parameters:
195 | * handle: wav descriptor to work on
196 | * Return Value:
197 | * suggested size of buffer for R/W operations
198 | * Side effects:
199 | * N/A
200 | * Preconditions:
201 | * Of course given wav handle is must be a valid one obtained as return
202 | * value of wav_open/wav_fdopen; additionally, wav header for given
203 | * descriptor must be fully avalaible.
204 | * This is always true if wav file was opened in read mode. If wav file
205 | * was opened in write mode, caller must ensure to issue all stream
206 | * parameters using wav_set_ (and possibly to use
207 | * wav_write_header) BEFORE to use this function.
208 | * Otherwise, caller will get an unreliable result (aka: garbage).
209 | * Postconditions:
210 | * N/A
211 | */
212 | uint32_t wav_chunk_size(WAV handle, double fps);
213 |
214 | /*
215 | * wav_last_error:
216 | * get descriptor of last error related to given wav descriptor.
217 | *
218 | * Parameters:
219 | * handle: a wav descriptor.
220 | * Return Value:
221 | * code of last error occurred.
222 | * Side effects:
223 | * N/A
224 | * Preconditions:
225 | * given wav descriptor was obtained as valid return value of
226 | * wav_open/wav_fdopen.
227 | * Postconditions:
228 | * N/A
229 | */
230 | WAVError wav_last_error(WAV handle);
231 |
232 | /*
233 | * wav_strerror:
234 | * get a human-readable short description of an error code
235 | *
236 | * Parameters:
237 | * err: error code to describe
238 | * Return Value:
239 | * a pointer to a C-string describing the given error code,
240 | * or NULL if given error code isn't known.
241 | * Side effects:
242 | * N/A
243 | * Preconditions:
244 | * N/A
245 | * Postconditions:
246 | * N/A
247 | */
248 | const char *wav_strerror(WAVError err);
249 |
250 | /*
251 | * wav_write_header:
252 | * update header for WAVE file using information stored
253 | * in attached WAV descriptor.
254 | * This function MAKE NO SENSE if applied to a WAV
255 | * descriptor open in WAV_READ mode.
256 | *
257 | * IMPORTANT NOTICE:
258 | * If wav_write_header is applied to a WAV descriptor
259 | * using WAV_WRITE|WAV_PIPE mode, *it doesn't seek at all*,
260 | * so it will simply write the full WAVE header into
261 | * stream at current position.
262 | * This actually is a *design decision*, the intended usage
263 | * of this function when dealing with WAV_WRITE|WAV_PIPE
264 | * descriptor is something like this:
265 | *
266 | * WAV wav = wav_fdopen(my_fd, WAV_WRITE|WAV_PIPE, NULL);
267 | *
268 | *
269 | *
270 | * wav_write_header(wav, 1);
271 | *
272 | * while (1) {
273 | * bytes = get_data(buffer, bufsize);
274 | * if(no_more_data()) {
275 | * break;
276 | * }
277 | * if (wav_write_data(wav, buffer, bytes) != 0) {
278 | * break;
279 | * }
280 | * }
281 | *
282 | * Parameters:
283 | * handle: update header for WAVE file attached to this
284 | * descriptor
285 | * force: if !0, update header even if isn't needed
286 | * Return Value:
287 | * 0 successfull, -1 otherwise
288 | * Side effects:
289 | * WAVE header is (re)written on file. This usually
290 | * requires some seeks on file.
291 | * See above if WAV_PIPE mode is used
292 | * Preconditions:
293 | * given wav descriptor is a valid one obtained as return value of
294 | * wav_open or wav_fdopen.
295 | * Postconditions:
296 | * N/A
297 | */
298 | int wav_write_header(WAV handle, int force);
299 |
300 |
301 | /*
302 | * wav_{get,set}_*:
303 | * set or get interesting WAV parameters.
304 | * wav_get_* functions can always be used if WAV descriptor is both
305 | * in read or write mode, but wav_set_* functions hare honoured
306 | * only if wav descriptor is in write mode.
307 | * wav_set_* functions applied to a read-mode wav are silently
308 | * discarderd.
309 | *
310 | * avalaible parameters:
311 | * rate (Average Samples Per Second): quantization rate of stream, Hz.
312 | * channels: number of channels in stream.
313 | * bits: size in bits for every sample.
314 | * bitrate (derived from Average Bytes per Second):
315 | * bytes needed to store a second of data.
316 | * Expressed in *KILOBIT/second*.
317 | *
318 | * Parameters:
319 | * handle: handle to a WAV descriptor returned by wav_open/wav_fdopen.
320 | * : (only wav_set_*) value of parameter to set in descriptor.
321 | * Return Value:
322 | * wav_get_*: value of requested parameter.
323 | * wav_set_*: None.
324 | * Side effects:
325 | * N/A
326 | * Preconditions:
327 | * given wav descriptor is a valid one obtained as return value of
328 | * wav_open or wav_fdopen.
329 | * Postconditions:
330 | * N/A
331 | */
332 |
333 | uint16_t wav_get_rate(WAV handle);
334 | void wav_set_rate(WAV handle, uint16_t rate);
335 |
336 | uint8_t wav_get_channels(WAV handle);
337 | void wav_set_channels(WAV handle, uint8_t channels);
338 |
339 | uint8_t wav_get_bits(WAV handle);
340 | void wav_set_bits(WAV handle, uint8_t bits);
341 |
342 | uint32_t wav_get_bitrate(WAV handle);
343 | void wav_set_bitrate(WAV handle, uint32_t bitrate);
344 |
345 | #endif /* _WAVLIB_H_ */
346 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/aviplayer/AviPlayer.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/30.
3 | //
4 |
5 | #include "AviPlayer.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | struct Instance {
13 | char *buffer;
14 | GLuint texture;
15 |
16 | Instance() : buffer(0), texture(0) {
17 |
18 | }
19 | };
20 |
21 | JNIEXPORT jlong JNICALL
22 | Java_com_glumes_cppso_aviplayer_AviPlayer_open(JNIEnv *env, jclass, jstring fileName) {
23 | avi_t *avi = 0;
24 | const char *filename = env->GetStringUTFChars(fileName, NULL);
25 | if (filename == NULL) {
26 | return (jlong) avi;
27 | }
28 |
29 | avi = AVI_open_input_file(filename, 1);
30 |
31 | env->ReleaseStringUTFChars(fileName, filename);
32 |
33 | if (avi == 0) {
34 | throwByName(env, IOException, "debug info");
35 | }
36 |
37 | return (jlong) avi;
38 |
39 | }
40 |
41 | JNIEXPORT jint JNICALL
42 | Java_com_glumes_cppso_aviplayer_AviPlayer_getWidth(JNIEnv *env, jclass, jlong avi) {
43 | return AVI_video_width((avi_t *) avi);
44 | }
45 |
46 | JNIEXPORT jint JNICALL
47 | Java_com_glumes_cppso_aviplayer_AviPlayer_getHeight(JNIEnv *env, jclass, jlong avi) {
48 | return AVI_video_height((avi_t *) avi);
49 | }
50 |
51 | JNIEXPORT jdouble JNICALL
52 | Java_com_glumes_cppso_aviplayer_AviPlayer_getFrameRate(JNIEnv *env, jclass, jlong avi) {
53 | return AVI_frame_rate((avi_t *) avi);
54 | }
55 |
56 | JNIEXPORT void JNICALL
57 | Java_com_glumes_cppso_aviplayer_AviPlayer_close(JNIEnv *env, jclass, jlong avi) {
58 | AVI_close((avi_t *) avi);
59 | }
60 |
61 |
62 | JNIEXPORT jboolean JNICALL
63 | Java_com_glumes_cppso_aviplayer_AviPlayer_render(JNIEnv *env, jclass jcls, jlong avi,
64 | jobject bitmap) {
65 | jboolean isFrameRead = JNI_FALSE;
66 | char *frameBuffer = 0;
67 | long frameSize = 0;
68 | int keyFrame = 0;
69 |
70 | if (AndroidBitmap_lockPixels(env, bitmap, (void **) &frameBuffer) < 0) {
71 | throwByName(env, IOException, "Unable to lock pixels.");
72 | return JNI_FALSE;
73 | }
74 |
75 | frameSize = AVI_read_frame((avi_t *) avi, frameBuffer, &keyFrame);
76 |
77 | if (AndroidBitmap_unlockPixels(env, bitmap) < 0) {
78 | throwByName(env, IOException, "Unable to unlock pixels.");
79 | }
80 |
81 | if (frameSize > 0) {
82 | isFrameRead = JNI_TRUE;
83 | }
84 |
85 | return isFrameRead;
86 |
87 | }
88 |
89 |
90 | // opengl 渲染相关
91 | JNIEXPORT jlong JNICALL
92 | Java_com_glumes_cppso_aviplayer_AviPlayer_init(JNIEnv *env, jclass, jlong avi) {
93 | Instance *instance = 0;
94 | long frameSize = AVI_frame_size((avi_t *) avi, 0);
95 | if (frameSize <= 0) {
96 | throwByName(env, RuntimeException, "Unable to get the frame size.");
97 | return 0;
98 | }
99 | instance = new Instance();
100 |
101 | instance->buffer = (char *) malloc(frameSize);
102 | if (instance->buffer == 0) {
103 | throwByName(env, RuntimeException, "Unable to allocate buffer.");
104 | delete instance;
105 | instance = 0;
106 | }
107 |
108 | return (jlong) instance;
109 | }
110 |
111 | JNIEXPORT void JNICALL
112 | Java_com_glumes_cppso_aviplayer_AviPlayer_initSurface(JNIEnv *env, jclass clazz, jlong inst,
113 | jlong avi) {
114 | Instance *instance = (Instance *) inst;
115 | glEnable(GL_TEXTURE_2D);
116 |
117 | glGenTextures(1, &instance->texture);
118 |
119 | glBindTexture(GL_TEXTURE_2D, instance->texture);
120 |
121 | int frameWidth = AVI_video_width((avi_t *) avi);
122 | int frameHeight = AVI_video_height((avi_t *) avi);
123 |
124 | GLint rect[] = {0, frameHeight, frameWidth, -frameHeight};
125 | glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
126 |
127 | glColor4f(1.0, 1.0, 1.0, 1.0);
128 |
129 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, frameWidth, frameHeight, 0, GL_RGB,
130 | GL_UNSIGNED_SHORT_5_6_5, 0);
131 |
132 | }
133 |
134 | JNIEXPORT jboolean JNICALL
135 | Java_com_glumes_cppso_aviplayer_AviPlayer_glRender(JNIEnv *env, jclass, jlong inst, jlong avi) {
136 | Instance *instance = (Instance *) inst;
137 | jboolean isFrameRead = JNI_FALSE;
138 | int keyFrame = 0;
139 | long frameSize = AVI_read_frame((avi_t *) avi, instance->buffer, &keyFrame);
140 | if (frameSize <= 0) {
141 | return JNI_FALSE;
142 | }
143 | isFrameRead = JNI_TRUE;
144 | glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
145 | AVI_video_width((avi_t *) avi),
146 | AVI_video_height((avi_t *) avi),
147 | GL_RGB,
148 | GL_UNSIGNED_SHORT_5_6_5, instance->buffer);
149 |
150 | // glDrawTexiOES()
151 | }
152 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/aviplayer/AviPlayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/30.
3 | //
4 | #include
5 |
6 | #ifndef ANDROIDCPPSOLIB_AVIPLAYER_H
7 | #define ANDROIDCPPSOLIB_AVIPLAYER_H
8 |
9 |
10 | #ifdef __cplusplus
11 | extern "C" {
12 | #endif
13 |
14 | #include
15 | // 导入自己写的带函数声明的 头文件,要在 cpp 里面导入,.h 里面导入没效果
16 | //#include
17 | #include
18 | /*
19 | * Class: com_glumes_cppso_aviplayer_AviPlayer
20 | * Method: open
21 | * Signature: (Ljava/lang/String;)J
22 | */
23 | JNIEXPORT jlong JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_open
24 | (JNIEnv *, jclass, jstring);
25 |
26 | /*
27 | * Class: com_glumes_cppso_aviplayer_AviPlayer
28 | * Method: getWidth
29 | * Signature: (J)I
30 | */
31 | JNIEXPORT jint JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getWidth
32 | (JNIEnv *, jclass, jlong);
33 |
34 | /*
35 | * Class: com_glumes_cppso_aviplayer_AviPlayer
36 | * Method: getHeight
37 | * Signature: (J)I
38 | */
39 | JNIEXPORT jint JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getHeight
40 | (JNIEnv *, jclass, jlong);
41 |
42 | /*
43 | * Class: com_glumes_cppso_aviplayer_AviPlayer
44 | * Method: getFrameRate
45 | * Signature: (J)D
46 | */
47 | JNIEXPORT jdouble JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getFrameRate
48 | (JNIEnv *, jclass, jlong);
49 |
50 | /*
51 | * Class: com_glumes_cppso_aviplayer_AviPlayer
52 | * Method: close
53 | * Signature: (J)V
54 | */
55 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_close
56 | (JNIEnv *, jclass, jlong);
57 |
58 |
59 | /*
60 | * Class: com_glumes_cppso_aviplayer_AviPlayer
61 | * Method: render
62 | * Signature: (JLandroid/graphics/Bitmap;)Z
63 | */
64 | JNIEXPORT jboolean JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_render
65 | (JNIEnv *, jclass, jlong, jobject);
66 |
67 |
68 | /*
69 | * Class: com_glumes_cppso_aviplayer_AviPlayer
70 | * Method: init
71 | * Signature: (J)J
72 | */
73 | JNIEXPORT jlong JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_init
74 | (JNIEnv *, jclass, jlong);
75 |
76 | /*
77 | * Class: com_glumes_cppso_aviplayer_AviPlayer
78 | * Method: initSurface
79 | * Signature: (JJ)V
80 | */
81 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_initSurface
82 | (JNIEnv *, jclass, jlong, jlong);
83 |
84 | /*
85 | * Class: com_glumes_cppso_aviplayer_AviPlayer
86 | * Method: glRender
87 | * Signature: (JJ)Z
88 | */
89 | JNIEXPORT jboolean JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_glRender
90 | (JNIEnv *, jclass, jlong, jlong);
91 |
92 | /*
93 | * Class: com_glumes_cppso_aviplayer_AviPlayer
94 | * Method: free
95 | * Signature: (J)V
96 | */
97 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_free
98 | (JNIEnv *, jclass, jlong);
99 | #ifdef __cplusplus
100 | }
101 | #endif
102 |
103 | #endif //ANDROIDCPPSOLIB_AVIPLAYER_H
104 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/common/commonutil.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/29.
3 | //
4 |
5 | #include "commonutil.h"
6 |
7 | void throwByName(JNIEnv *env, const char *name, const char *msg) {
8 | jclass cls = env->FindClass(name);
9 | if (cls != NULL) {
10 | env->ThrowNew(cls, msg);
11 | }
12 | env->DeleteLocalRef(cls);
13 | }
14 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/common/commonutil.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/29.
3 | //
4 |
5 | #include
6 |
7 | #ifndef ANDROIDCPPSOLIB_COMMONUTIL_H
8 | #define ANDROIDCPPSOLIB_COMMONUTIL_H
9 |
10 |
11 | static const char *IOException = "java/io/IOException";
12 | static const char *RuntimeException = "java/io/RuntimeException";
13 |
14 | void throwByName(JNIEnv *env, const char *name, const char *msg);
15 |
16 | #endif //ANDROIDCPPSOLIB_COMMONUTIL_H
17 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/common/logutil.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/3/7.
3 | //
4 |
5 | #include
6 |
7 | #ifndef ANDROIDCPPSOLIB_LOGUTIL_H
8 | #define ANDROIDCPPSOLIB_LOGUTIL_H
9 |
10 |
11 | #define LOG_TAG "NativeMethod"
12 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
13 | #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
14 | #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)
15 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
16 |
17 |
18 |
19 |
20 | #endif //ANDROIDCPPSOLIB_LOGUTIL_H
21 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/infomanager/LoadManager.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/20.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | extern "C"
10 | JNIEXPORT void JNICALL
11 | Java_com_glumes_androidcppsolib_activity_InfoManageActivity_loadData(JNIEnv *env,
12 | jobject instance) {
13 |
14 | jfieldID itemFid;
15 | jclass cls = env->GetObjectClass(instance);
16 |
17 | itemFid = env->GetFieldID(cls, "mItems", "Lcom/glumes/databindingadapter/Items;");
18 |
19 | if (itemFid == NULL) {
20 | return;
21 | }
22 |
23 | jobject mItems = env->GetObjectField(instance, itemFid);
24 |
25 | if (mItems == NULL) {
26 | return;
27 | }
28 |
29 | jclass itemCls = env->GetObjectClass(mItems);
30 |
31 | jmethodID addMid;
32 |
33 | addMid = env->GetMethodID(itemCls, "add", "(Ljava/lang/Object;)Z");
34 |
35 | if (addMid == NULL) {
36 | return;
37 | }
38 |
39 | jclass stuClass = env->FindClass("com/glumes/androidcppsolib/binder/Student");
40 | if (stuClass == NULL) {
41 | return;
42 | }
43 |
44 | jmethodID stuInitMid = env->GetMethodID(stuClass, "",
45 | "(Ljava/lang/String;ILjava/lang/String;III)V");
46 |
47 | if (stuInitMid == NULL) {
48 | return;
49 | }
50 |
51 | jobject stu = env->NewObject(stuClass, stuInitMid, env->NewStringUTF("jni name"), 12,
52 | env->NewStringUTF("female"), 4, 123, 22);
53 |
54 | if (stu == NULL) {
55 | return;
56 | }
57 |
58 | jboolean result = env->CallBooleanMethod(mItems, addMid, stu);
59 |
60 |
61 | LOGD("add mid");
62 |
63 | }
64 |
65 |
66 | extern "C"
67 | JNIEXPORT void JNICALL
68 | Java_com_glumes_androidcppsolib_activity_InfoManageActivity_minusData(JNIEnv *env,
69 | jobject instance) {
70 |
71 | }
72 |
73 | extern "C"
74 | JNIEXPORT void JNICALL
75 | Java_com_glumes_androidcppsolib_activity_InfoManageActivity_plusData(JNIEnv *env,
76 | jobject instance) {
77 |
78 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/infomanager/Student.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/20.
3 | //
4 |
5 | #include "Student.h"
6 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/infomanager/Student.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/20.
3 | //
4 |
5 | #ifndef ANDROIDCPPSOLIB_STUDENT_H
6 | #define ANDROIDCPPSOLIB_STUDENT_H
7 |
8 |
9 | class Student {
10 |
11 | };
12 |
13 |
14 | #endif //ANDROIDCPPSOLIB_STUDENT_H
15 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/array-type-operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/4/22.
3 | //
4 | #include
5 | #include
6 |
7 |
8 | extern "C"
9 | JNIEXPORT jint JNICALL
10 | Java_com_glumes_cppso_jnioperations_ArrayTypeOps_intArraySum(JNIEnv *env, jobject instance,
11 | jintArray intArray_, jint num) {
12 | jint *intArray;
13 | int sum = 0;
14 |
15 | // 操作方法一:
16 |
17 | // 如同 getUTFString 一样,会申请 native 内存
18 | intArray = env->GetIntArrayElements(intArray_, NULL);
19 |
20 | if (intArray == NULL) {
21 | return 0;
22 | }
23 |
24 | // 得到数组的长度
25 | int length = env->GetArrayLength(intArray_);
26 | LOGD("array length is %d", length);
27 |
28 | for (int i = 0; i < length; ++i) {
29 | sum += intArray[i];
30 | }
31 |
32 | LOGD("sum is %d", sum);
33 |
34 | // 操作方法二:
35 |
36 | jint buf[num];
37 |
38 | env->GetIntArrayRegion(intArray_, 0, num, buf);
39 |
40 | sum = 0;
41 | for (int i = 0; i < num; ++i) {
42 | sum += buf[i];
43 | }
44 |
45 | LOGD("sum is %d", sum);
46 |
47 | // 使用完了别忘了释放内存
48 | env->ReleaseIntArrayElements(intArray_, intArray, 0);
49 |
50 | return sum;
51 | }
52 |
53 |
54 | /**
55 | * 从 Native 返回 int 数组,主要调用 setArrayRegion 来填充数据,其他数据类型类似操作
56 | */
57 | extern "C"
58 | JNIEXPORT jintArray JNICALL
59 | Java_com_glumes_cppso_jnioperations_ArrayTypeOps_getIntArray(JNIEnv *env, jobject instance,
60 | jint num) {
61 |
62 | jintArray intArray;
63 | intArray = env->NewIntArray(num);
64 |
65 | jint buf[num];
66 | for (int i = 0; i < num; ++i) {
67 | buf[i] = i * 2;
68 | }
69 |
70 | // 使用 setIntArrayRegion 来赋值
71 | env->SetIntArrayRegion(intArray, 0, num, buf);
72 | return intArray;
73 | }
74 |
75 |
76 |
77 |
78 | /**
79 | * 从 Native 返回一个二维的整型数组
80 | */
81 | extern "C"
82 | JNIEXPORT jobjectArray JNICALL
83 | Java_com_glumes_cppso_jnioperations_ArrayTypeOps_getTwoDimensionalArray(JNIEnv *env,
84 | jobject instance,
85 | jint size) {
86 | // 声明一个对象数组
87 | jobjectArray result;
88 | // 找到对象数组中具体的对象类型
89 | jclass intArrayCls = env->FindClass("[I");
90 |
91 | if (intArrayCls == NULL) {
92 | return NULL;
93 | }
94 | // 相当于初始化一个对象数组,用指定的对象类型
95 | result = env->NewObjectArray(size, intArrayCls, NULL);
96 |
97 | if (result == NULL) {
98 | return NULL;
99 | }
100 |
101 | for (int i = 0; i < size; ++i) {
102 | // 用来给整型数组填充数据的缓冲区
103 | jint tmp[256];
104 | // 声明一个整型数组
105 | jintArray iarr = env->NewIntArray(size);
106 | if (iarr == NULL) {
107 | return NULL;
108 | }
109 | for (int j = 0; j < size; ++j) {
110 | tmp[j] = i + j;
111 | }
112 | // 给整型数组填充数据
113 | env->SetIntArrayRegion(iarr, 0, size, tmp);
114 | // 给对象数组指定位置填充数据,这个数据就是一个一维整型数组
115 | env->SetObjectArrayElement(result, i, iarr);
116 | // 释放局部引用
117 | env->DeleteLocalRef(iarr);
118 | }
119 | return result;
120 | }
121 |
122 |
123 |
124 |
125 | /**
126 | * 打印对象数组中的信息
127 | */
128 | extern "C"
129 | JNIEXPORT void JNICALL
130 | Java_com_glumes_cppso_jnioperations_ArrayTypeOps_printAnimalsName(JNIEnv *env, jobject instance,
131 | jobjectArray animals) {
132 |
133 | jobject animal;
134 | // 数组长度
135 | int size = env->GetArrayLength(animals);
136 | // 数组中对应的类
137 | jclass cls = env->FindClass("com/glumes/cppso/model/Animal");
138 | // 类对应的字段描述
139 | jfieldID fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
140 | // 类的字段具体的值
141 | jstring jstr;
142 | // 类字段具体值转换成 C/C++ 字符串
143 | const char *str;
144 |
145 | for (int i = 0; i < size; ++i) {
146 | // 得到数组中的每一个元素
147 | animal = env->GetObjectArrayElement(animals, i);
148 | // 每一个元素具体字段的值
149 | jstr = (jstring) (env->GetObjectField(animal, fid));
150 |
151 | str = env->GetStringUTFChars(jstr, NULL);
152 |
153 | if (str == NULL) {
154 | continue;
155 | }
156 | LOGD("str is %s", str);
157 | env->ReleaseStringUTFChars(jstr, str);
158 | }
159 | }
160 |
161 |
162 |
163 | /**
164 | * 基本类型的数据传递
165 | */
166 | extern "C"
167 | JNIEXPORT void JNICALL
168 | Java_com_glumes_cppso_jnioperations_ArrayTypeOps_primitiveTypeArray(JNIEnv *env, jobject instance,
169 | jintArray intArray_,
170 | jfloatArray floatArray_,
171 | jdoubleArray doubleArray_,
172 | jshortArray shortArray_,
173 | jlongArray longArray_,
174 | jbooleanArray boolArray_,
175 | jcharArray charArray_,
176 | jbyteArray byteArray_) {
177 | jint *intArray = env->GetIntArrayElements(intArray_, NULL);
178 | jfloat *floatArray = env->GetFloatArrayElements(floatArray_, NULL);
179 | jdouble *doubleArray = env->GetDoubleArrayElements(doubleArray_, NULL);
180 | jshort *shortArray = env->GetShortArrayElements(shortArray_, NULL);
181 | jlong *longArray = env->GetLongArrayElements(longArray_, NULL);
182 | jboolean *boolArray = env->GetBooleanArrayElements(boolArray_, NULL);
183 | jchar *charArray = env->GetCharArrayElements(charArray_, NULL);
184 | jbyte *byteArray = env->GetByteArrayElements(byteArray_, NULL);
185 |
186 |
187 |
188 | // 基础数据类型的操作,大同小异
189 | // 可用函数
190 | // 1、GetArrayElements / ReleaseArrayElements
191 | // 2、GetArrayRegion / SetArrayRegion
192 | // 3、GetArrayLength
193 |
194 |
195 | env->ReleaseIntArrayElements(intArray_, intArray, 0);
196 | env->ReleaseFloatArrayElements(floatArray_, floatArray, 0);
197 | env->ReleaseDoubleArrayElements(doubleArray_, doubleArray, 0);
198 | env->ReleaseShortArrayElements(shortArray_, shortArray, 0);
199 | env->ReleaseLongArrayElements(longArray_, longArray, 0);
200 | env->ReleaseBooleanArrayElements(boolArray_, boolArray, 0);
201 | env->ReleaseCharArrayElements(charArray_, charArray, 0);
202 | env->ReleaseByteArrayElements(byteArray_, byteArray, 0);
203 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/basic-type-operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/4/22.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | #include
10 |
11 |
12 | // 八种基本数据类型 从 Java 到 JNI 的类型转换操作
13 |
14 | // JNI 的基础数据类型在 Java 的基础类型上加了一个 j
15 | // 查看源码,JNI 的基础数据类型就是在 C/C++ 基础之上,通过 typedef 声明的别名
16 |
17 | ///* Primitive types that match up with Java equivalents. */
18 | //typedef uint8_t jboolean; /* unsigned 8 bits */
19 | //typedef int8_t jbyte; /* signed 8 bits */
20 | //typedef uint16_t jchar; /* unsigned 16 bits */
21 | //typedef int16_t jshort; /* signed 16 bits */
22 | //typedef int32_t jint; /* signed 32 bits */
23 | //typedef int64_t jlong; /* signed 64 bits */
24 | //typedef float jfloat; /* 32-bit IEEE 754 */
25 | //typedef double jdouble; /* 64-bit IEEE 754 */
26 |
27 |
28 |
29 | extern "C"
30 | JNIEXPORT jint JNICALL
31 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeInt(JNIEnv *env, jobject instance,
32 | jint num) {
33 |
34 | LOGD("java int value is %d", num);
35 | int c_num = num * 2;
36 | return c_num;
37 | }
38 |
39 |
40 | extern "C"
41 | JNIEXPORT jbyte JNICALL
42 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeByte(JNIEnv *env, jobject instance,
43 | jbyte b) {
44 |
45 | LOGD("java byte value is %d", b);
46 | jbyte c_byte = b + (jbyte) 10;
47 | return c_byte;
48 | }
49 |
50 |
51 | extern "C"
52 | JNIEXPORT jchar JNICALL
53 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeChar(JNIEnv *env, jobject instance,
54 | jchar ch) {
55 |
56 | LOGD("java char value is %c", ch);
57 | jchar c_char = ch + (jchar) 3;
58 | return c_char;
59 | }
60 |
61 |
62 | extern "C"
63 | JNIEXPORT jshort JNICALL
64 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeShort(JNIEnv *env, jobject instance,
65 | jshort sh) {
66 |
67 | LOGD("java char value is %d", sh);
68 | jshort c_short = sh + (jshort) 10;
69 | return c_short;
70 | }
71 |
72 | extern "C"
73 | JNIEXPORT jlong JNICALL
74 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeLong(JNIEnv *env, jobject instance,
75 | jlong l) {
76 |
77 | LOGD("java long value is %d", l);
78 | jlong c_long = l + 100;
79 | return c_long;
80 | }
81 |
82 |
83 |
84 | extern "C"
85 | JNIEXPORT jfloat JNICALL
86 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeFloat(JNIEnv *env, jobject instance,
87 | jfloat f) {
88 |
89 | LOGD("java float value is %f", f);
90 | jfloat c_float = f + (jfloat) 10.0;
91 | return c_float;
92 | }
93 |
94 |
95 |
96 | extern "C"
97 | JNIEXPORT jdouble JNICALL
98 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeDouble(JNIEnv *env, jobject instance,
99 | jdouble d) {
100 |
101 | LOGD("java double value is %f", d);
102 | jdouble c_double = d + 20.0;
103 | return c_double;
104 | }
105 |
106 |
107 | extern "C"
108 | JNIEXPORT jboolean JNICALL
109 | Java_com_glumes_cppso_jnioperations_BasicTypeOps_callNativeBoolean(JNIEnv *env, jobject instance,
110 | jboolean value) {
111 | LOGD("java boolean value is %d", value);
112 | jboolean c_bool = (jboolean) !value;
113 | return c_bool;
114 | }
115 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/bitmap_operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/7/24.
3 | //
4 |
5 | #include
6 |
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | jobject generateBitmap(JNIEnv *env, uint32_t width, uint32_t height);
13 |
14 | extern "C"
15 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_rotateBitmap
16 | (JNIEnv *env, jobject, jobject bitmap) {
17 | LOGD("rotate bitmap");
18 |
19 | AndroidBitmapInfo bitmapInfo;
20 | int ret;
21 | if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) {
22 | LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
23 | return NULL;
24 | }
25 |
26 | // 读取 bitmap 的像素内容到 native 内存
27 | void *bitmapPixels;
28 | if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {
29 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
30 | return NULL;
31 | }
32 |
33 | uint32_t newWidth = bitmapInfo.height;
34 | uint32_t newHeight = bitmapInfo.width;
35 |
36 | uint32_t *newBitmapPixels = new uint32_t[newWidth * newHeight];
37 |
38 | int whereToGet = 0;
39 |
40 | // 弄明白 bitmapPixels 的排列,这里不同于二维数组了。
41 | for (int x = newWidth; x >= 0; --x) {
42 | for (int y = 0; y < newHeight; ++y) {
43 | uint32_t pixel = ((uint32_t *) bitmapPixels)[whereToGet++];
44 | newBitmapPixels[newWidth * y + x] = pixel;
45 | }
46 | }
47 |
48 | jobject newBitmap = generateBitmap(env, newWidth, newHeight);
49 |
50 | void *resultBitmapPixels;
51 |
52 | if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &resultBitmapPixels)) < 0) {
53 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
54 | return NULL;
55 | }
56 |
57 | int pixelsCount = newWidth * newHeight;
58 |
59 | memcpy((uint32_t *) resultBitmapPixels, newBitmapPixels, sizeof(uint32_t) * pixelsCount);
60 |
61 | AndroidBitmap_unlockPixels(env, newBitmap);
62 |
63 | delete[] newBitmapPixels;
64 | return newBitmap;
65 | }
66 |
67 | extern "C"
68 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_convertBitmap
69 | (JNIEnv *env, jobject, jobject bitmap) {
70 | LOGD("convert bitmap");
71 | AndroidBitmapInfo bitmapInfo;
72 | int ret;
73 | if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) {
74 | LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
75 | return NULL;
76 | }
77 |
78 | // 读取 bitmap 的像素内容到 native 内存
79 | void *bitmapPixels;
80 | if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {
81 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
82 | return NULL;
83 | }
84 |
85 | uint32_t newWidth = bitmapInfo.width;
86 | uint32_t newHeight = bitmapInfo.height;
87 |
88 | uint32_t *newBitmapPixels = new uint32_t[newWidth * newHeight];
89 |
90 | int whereToGet = 0;
91 |
92 | for (int y = 0; y < newHeight; ++y) {
93 | for (int x = 0; x < newWidth; x++) {
94 | uint32_t pixel = ((uint32_t *) bitmapPixels)[whereToGet++];
95 | newBitmapPixels[newWidth * (newHeight - 1 - y) + x] = pixel;
96 | }
97 | }
98 |
99 |
100 | jobject newBitmap = generateBitmap(env, newWidth, newHeight);
101 |
102 | void *resultBitmapPixels;
103 |
104 | if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &resultBitmapPixels)) < 0) {
105 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
106 | return NULL;
107 | }
108 |
109 | int pixelsCount = newWidth * newHeight;
110 |
111 | memcpy((uint32_t *) resultBitmapPixels, newBitmapPixels, sizeof(uint32_t) * pixelsCount);
112 |
113 | AndroidBitmap_unlockPixels(env, newBitmap);
114 |
115 | delete[] newBitmapPixels;
116 |
117 | return newBitmap;
118 | }
119 |
120 | extern "C"
121 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_mirrorBitmap
122 | (JNIEnv *env, jobject, jobject bitmap) {
123 | LOGD("mirror bitmap");
124 | AndroidBitmapInfo bitmapInfo;
125 | int ret;
126 | if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) {
127 | LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
128 | return NULL;
129 | }
130 |
131 | // 读取 bitmap 的像素内容到 native 内存
132 | void *bitmapPixels;
133 | if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {
134 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
135 | return NULL;
136 | }
137 |
138 | uint32_t newWidth = bitmapInfo.width;
139 | uint32_t newHeight = bitmapInfo.height;
140 |
141 | uint32_t *newBitmapPixels = new uint32_t[newWidth * newHeight];
142 |
143 | int whereToGet = 0;
144 |
145 | for (int y = 0; y < newHeight; ++y) {
146 | for (int x = newWidth - 1; x >= 0; x--) {
147 | uint32_t pixel = ((uint32_t *) bitmapPixels)[whereToGet++];
148 | newBitmapPixels[newWidth * y + x] = pixel;
149 | }
150 | }
151 |
152 |
153 | jobject newBitmap = generateBitmap(env, newWidth, newHeight);
154 |
155 | void *resultBitmapPixels;
156 |
157 | if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &resultBitmapPixels)) < 0) {
158 | LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
159 | return NULL;
160 | }
161 |
162 | int pixelsCount = newWidth * newHeight;
163 |
164 | memcpy((uint32_t *) resultBitmapPixels, newBitmapPixels, sizeof(uint32_t) * pixelsCount);
165 |
166 | AndroidBitmap_unlockPixels(env, newBitmap);
167 |
168 | delete[] newBitmapPixels;
169 |
170 | return newBitmap;
171 | }
172 |
173 |
174 | jobject generateBitmap(JNIEnv *env, uint32_t width, uint32_t height) {
175 |
176 | jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
177 | jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls,
178 | "createBitmap",
179 | "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
180 | jstring configName = env->NewStringUTF("ARGB_8888");
181 | jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
182 | jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(
183 | bitmapConfigClass, "valueOf",
184 | "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
185 |
186 | jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass,
187 | valueOfBitmapConfigFunction, configName);
188 |
189 | jobject newBitmap = env->CallStaticObjectMethod(bitmapCls,
190 | createBitmapFunction,
191 | width,
192 | height, bitmapConfig);
193 |
194 | return newBitmap;
195 | }
196 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/cache_filed_and_method.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/3.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | // 全局变量,作为缓存方法 id
9 | jmethodID InstanceMethodCache;
10 |
11 | extern "C"
12 | JNIEXPORT void JNICALL
13 | Java_com_glumes_cppso_jnioperations_CacheFieldAndMethodOps_staticCacheField(JNIEnv *env, jobject instance, jobject animal) {
14 | static jfieldID fid = NULL; // 声明为 static 变量进行缓存
15 |
16 | // 两种方法都行
17 | // jclass cls = env->GetObjectClass(animal);
18 | jclass cls = env->FindClass("com/glumes/cppso/model/Animal");
19 |
20 | jstring jstr;
21 |
22 | const char *c_str;
23 | // 从缓存中查找
24 | if (fid == NULL) {
25 | fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
26 | if (fid == NULL) {
27 | return;
28 | }
29 | } else {
30 | LOGD("field id is cached");
31 | }
32 |
33 | jstr = (jstring) env->GetObjectField(animal, fid);
34 | c_str = env->GetStringUTFChars(jstr, NULL);
35 | if (c_str == NULL) {
36 | return;
37 | }
38 | env->ReleaseStringUTFChars(jstr, c_str);
39 | jstr = env->NewStringUTF("new name");
40 | if (jstr == NULL) {
41 | return;
42 | }
43 | env->SetObjectField(animal, fid, jstr);
44 | }
45 |
46 | /**
47 | * 初始化加载时缓存方法 id
48 | */
49 | extern "C"
50 | JNIEXPORT void JNICALL
51 | Java_com_glumes_cppso_jnioperations_CacheFieldAndMethodOps_initCacheMethodId(JNIEnv *env,
52 | jclass type) {
53 | jclass cls = env->FindClass("com/glumes/cppso/model/Animal");
54 | InstanceMethodCache = env->GetMethodID(cls, "getName", "()Ljava/lang/String;");
55 | }
56 |
57 |
58 | extern "C"
59 | JNIEXPORT void JNICALL
60 | Java_com_glumes_cppso_jnioperations_CacheFieldAndMethodOps_callCacheMethod(JNIEnv *env, jobject instance, jobject animal) {
61 | jstring name = (jstring) env->CallObjectMethod(animal, InstanceMethodCache);
62 | const char *c_name = env->GetStringUTFChars(name, NULL);
63 | LOGD("call cache method and value is %s", c_name);
64 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/exceptions-operations.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/14.
3 | //
4 |
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | extern "C"
11 | JNIEXPORT void JNICALL
12 | Java_com_glumes_cppso_jnioperations_ExceptionOps_doit(JNIEnv *env, jobject instance) {
13 |
14 |
15 | jthrowable exc;
16 | jobject obj;
17 | jclass cls = env->FindClass("com/glumes/cppso/jnioperations/ExceptionOps");
18 |
19 | jmethodID initMid = env->GetMethodID(cls, "", "()V");
20 |
21 | obj = env->NewObject(cls, initMid);
22 |
23 | jmethodID mid = env->GetMethodID(cls, "callback", "()V");
24 |
25 | if (mid == NULL) {
26 | return;
27 | }
28 |
29 | env->CallVoidMethod(obj, mid);
30 |
31 | exc = env->ExceptionOccurred();
32 |
33 | if (exc) {
34 | jclass newExcCls;
35 | env->ExceptionDescribe();
36 | env->ExceptionClear();
37 | newExcCls = env->FindClass("java/lang/IllegalArgumentException");
38 | if (newExcCls == NULL) {
39 | return;
40 | }
41 | env->ThrowNew(newExcCls, "Thrown from C++ code");
42 | }
43 | }
44 |
45 |
46 |
47 | extern "C"
48 | JNIEXPORT void JNICALL
49 | Java_com_glumes_cppso_jnioperations_ExceptionOps_nativeThrowException(JNIEnv *env, jobject instance) {
50 | throwByName(env, "java/lang/IllegalArgumentException", "native throw exception");
51 | }
52 |
53 |
54 | /**
55 | * Native 代码调用 Java 的函数,引发了异常
56 | */
57 | extern "C"
58 | JNIEXPORT void JNICALL
59 | Java_com_glumes_cppso_jnioperations_ExceptionOps_nativeInvokeJavaException(JNIEnv *env,
60 | jobject instance) {
61 |
62 | jclass cls = env->FindClass("com/glumes/cppso/jnioperations/ExceptionOps");
63 | jmethodID mid = env->GetMethodID(cls, "", "()V");
64 | jobject obj = env->NewObject(cls, mid);
65 |
66 |
67 | mid = env->GetMethodID(cls, "operation", "()I");
68 |
69 | env->CallIntMethod(obj, mid);
70 |
71 | //检查是否发生了异常
72 | jthrowable exc = env->ExceptionOccurred();
73 | // jboolean result = env->ExceptionCheck();
74 |
75 | if (exc) {
76 | // 打印日志
77 | env->ExceptionDescribe();
78 | // 这代码才是关键不让应用崩溃的代码
79 | env->ExceptionClear();
80 | // 发生异常了要记得释放资源
81 | env->DeleteLocalRef(cls);
82 | env->DeleteLocalRef(obj);
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/filed_and_method_operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/4/26.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | // 访问类的实例的字段
9 | extern "C"
10 | JNIEXPORT void JNICALL
11 | Java_com_glumes_cppso_jnioperations_FieldAndMethodOps_accessInstanceFiled(JNIEnv *env,
12 | jobject instance,
13 | jobject animal) {
14 |
15 | jfieldID fid;
16 | jstring jstr;
17 | const char *str;
18 |
19 | jclass cls = env->GetObjectClass(animal);
20 |
21 | fid = env->GetFieldID(cls, "name", "Ljava/lang/String;");
22 |
23 | if (fid == NULL) {
24 | return;
25 | }
26 |
27 | jstr = (jstring) env->GetObjectField(animal, fid);
28 |
29 | str = env->GetStringUTFChars(jstr, NULL);
30 |
31 | if (str == NULL) {
32 | return;
33 | }
34 |
35 | LOGD("name is %s", str);
36 |
37 | env->ReleaseStringUTFChars(jstr, str);
38 |
39 | jstr = env->NewStringUTF("replaced name");
40 |
41 | if (jstr == NULL) {
42 | return;
43 | }
44 |
45 | env->SetObjectField(animal, fid, jstr);
46 |
47 | }
48 |
49 |
50 | // 访问类的静态字段
51 | extern "C"
52 | JNIEXPORT void JNICALL
53 | Java_com_glumes_cppso_jnioperations_FieldAndMethodOps_accessStaticField(JNIEnv *env,
54 | jobject instance,
55 | jobject animal) {
56 |
57 | jfieldID fid;
58 | jint num;
59 |
60 | jclass cls = env->GetObjectClass(animal);
61 |
62 | fid = env->GetStaticFieldID(cls, "num", "I");
63 |
64 | if (fid == NULL) {
65 | return;
66 | }
67 |
68 | num = env->GetStaticIntField(cls, fid);
69 |
70 | LOGD("get static field num is %d", num);
71 |
72 | env->SetStaticIntField(cls, fid, ++num);
73 |
74 |
75 | }
76 |
77 |
78 | // Native 访问 Java 的类实例方法
79 | extern "C"
80 | JNIEXPORT void JNICALL
81 | Java_com_glumes_cppso_jnioperations_FieldAndMethodOps_callInstanceMethod(JNIEnv *env,
82 | jobject instance,
83 | jobject animal) {
84 |
85 | jclass cls = env->GetObjectClass(animal);
86 |
87 | jmethodID mid = env->GetMethodID(cls, "callInstanceMethod", "(I)V");
88 |
89 | if (mid == NULL) {
90 | return;
91 | }
92 |
93 | env->CallVoidMethod(animal, mid, 2);
94 |
95 | }
96 |
97 |
98 | // Native 访问 Java 的静态方法
99 | extern "C"
100 | JNIEXPORT void JNICALL
101 | Java_com_glumes_cppso_jnioperations_FieldAndMethodOps_callStaticMethod(JNIEnv *env,
102 | jobject instance,
103 | jobject animal) {
104 | jclass cls = env->GetObjectClass(animal);
105 |
106 | jmethodID argsmid = env->GetStaticMethodID(cls, "callStaticMethod",
107 | "(Ljava/lang/String;)Ljava/lang/String;");
108 |
109 | if (argsmid == NULL) {
110 | return;
111 | }
112 |
113 | jstring jstr = env->NewStringUTF("jstring");
114 |
115 | env->CallStaticObjectMethod(cls, argsmid, jstr);
116 |
117 | // ----
118 |
119 | argsmid = env->GetStaticMethodID(cls, "callStaticMethod",
120 | "([Ljava/lang/String;I)Ljava/lang/String;");
121 |
122 | if (argsmid == NULL) {
123 | return;
124 | }
125 |
126 | jobjectArray objArray;
127 |
128 | jclass objclass = env->FindClass("java/lang/String");
129 |
130 | if (objclass == NULL) {
131 | return;
132 | }
133 |
134 | int size = 3;
135 | objArray = env->NewObjectArray(size, objclass, NULL);
136 |
137 | if (objArray == NULL) {
138 | return;
139 | }
140 |
141 | jstring strElement;
142 |
143 | for (int i = 0; i < size; ++i) {
144 |
145 | strElement = env->NewStringUTF("str in c");
146 |
147 | env->SetObjectArrayElement(objArray, i, strElement);
148 | }
149 |
150 | env->CallStaticObjectMethod(cls, argsmid, objArray, 3);
151 |
152 | }
153 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/invoke_constructor.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/3.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | extern "C"
10 | JNIEXPORT jstring JNICALL
11 | Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_invokeStringConstructors(JNIEnv *env,
12 | jobject instance) {
13 |
14 | jclass stringClass;
15 | jmethodID cid;
16 | jcharArray elemArr;
17 | jstring result;
18 |
19 | // 由 C++ 字符串创建一个 Java 字符串
20 | jstring temp = env->NewStringUTF("this is char array");
21 | // 再从 Java 字符串获得一个字符数组指针,作为 String 构造函数的参数
22 | const jchar *chars = env->GetStringChars(temp, NULL);
23 | int len = 10;
24 |
25 | stringClass = env->FindClass("java/lang/String"); // 找到具体的 String 类
26 | if (stringClass == NULL) {
27 | return NULL;
28 | }
29 | // 找到具体的方法,([C)V 表示选择 String 的 String(char value[]) 构造方法
30 | cid = env->GetMethodID(stringClass, "", "([C)V");
31 | if (cid == NULL) {
32 | return NULL;
33 | }
34 | // 字符串数组作为参数
35 | elemArr = env->NewCharArray(len);
36 | if (elemArr == NULL) {
37 | return NULL;
38 | }
39 | // 给字符串数组赋值
40 | env->SetCharArrayRegion(elemArr, 0, len, chars);
41 |
42 | result = (jstring) env->NewObject(stringClass, cid, elemArr);
43 |
44 | env->DeleteLocalRef(elemArr);
45 | env->DeleteLocalRef(stringClass);
46 |
47 | return result;
48 | }
49 |
50 |
51 | /**
52 | * 创建一个 Java 的 Animal 类并返回
53 | */
54 | extern "C"
55 | JNIEXPORT jobject JNICALL
56 | Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_invokeAnimalConstructors(JNIEnv *env,
57 | jobject instance) {
58 |
59 | jclass animalClass;
60 | jmethodID mid;
61 |
62 | jobject result;
63 | animalClass = env->FindClass("com/glumes/cppso/model/Animal");
64 | if (animalClass == NULL) {
65 | return NULL;
66 | }
67 |
68 | mid = env->GetMethodID(animalClass, "", "(Ljava/lang/String;)V");
69 |
70 | if (mid == NULL) {
71 | return NULL;
72 | }
73 |
74 | jstring args = env->NewStringUTF("this animal name");
75 |
76 | result = env->NewObject(animalClass, mid, args);
77 |
78 | env->DeleteLocalRef(animalClass);
79 |
80 | return result;
81 |
82 | }
83 |
84 |
85 | /**
86 | * 通过 AllocObject 方法来创建一个类
87 | */
88 | extern "C"
89 | JNIEXPORT jobject JNICALL
90 | Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_allocObjectConstructor(JNIEnv *env,
91 | jobject instance) {
92 | jclass animalClass;
93 | jobject result;
94 | jmethodID mid;
95 | // 获得对应的 列
96 | animalClass = env->FindClass("com/glumes/cppso/model/Animal");
97 | if (animalClass == NULL) {
98 | return NULL;
99 | }
100 | // 获得构造方法 id
101 | mid = env->GetMethodID(animalClass, "", "(Ljava/lang/String;)V");
102 | if (mid == NULL) {
103 | return NULL;
104 | }
105 | // 构造方法的参数
106 | jstring args = env->NewStringUTF("use AllocObject");
107 | // 创建对象,此时创建的对象未初始化的对象
108 | result = env->AllocObject(animalClass);
109 | if (result == NULL) {
110 | return NULL;
111 | }
112 | // 调用 CallNonvirtualVoidMethod 方法去调用类的构造方法
113 | env->CallNonvirtualVoidMethod(result, animalClass, mid, args);
114 | if (env->ExceptionCheck()) {
115 | env->DeleteLocalRef(result);
116 | return NULL;
117 | }
118 | return result;
119 | }
120 |
121 |
122 | /**
123 | * 调用父类的方法
124 | * 创建一个子类,由子类去调用父类的方法
125 | */
126 | extern "C"
127 | JNIEXPORT void JNICALL
128 | Java_com_glumes_cppso_jnioperations_InvokeConstructorOps_callSuperMethod(JNIEnv *env, jobject instance) {
129 |
130 | jclass cat_cls; // Cat 类的类型
131 | jmethodID cat_cid; // Cat 类的构造方法 id
132 | jstring cat_name; // Cat 类的构造方法参数
133 | jobject cat;
134 | // 获得对应的 类
135 | cat_cls = env->FindClass("com/glumes/cppso/model/Cat");
136 | if (cat_cls == NULL) {
137 | return;
138 | }
139 | // 获得构造方法 id
140 | cat_cid = env->GetMethodID(cat_cls, "", "(Ljava/lang/String;)V");
141 | if (cat_cid == NULL) {
142 | return;
143 | }
144 | // 准备构造方法的参数
145 | cat_name = env->NewStringUTF("this is cat name");
146 | // 创建 Cat 类
147 | cat = env->NewObject(cat_cls, cat_cid, cat_name);
148 | if (cat == NULL) {
149 | return;
150 | }
151 |
152 | //调用父类的 getName 参数
153 | jclass animal_cls; // 父类的类型
154 | jmethodID animal_mid; // 被调用的父类的方法 id
155 | // 获得父类对应的类
156 | animal_cls = env->FindClass("com/glumes/cppso/model/Animal");
157 | if (animal_cls == NULL) {
158 | return;
159 | }
160 | // 获得父类被调用的方法 id
161 | animal_mid = env->GetMethodID(animal_cls, "getName", "()Ljava/lang/String;");
162 | if (animal_mid == NULL) {
163 | return;
164 | }
165 |
166 | jstring name = (jstring) env->CallNonvirtualObjectMethod(cat, animal_cls, animal_mid);
167 |
168 | if (name == NULL) {
169 | return;
170 | }
171 |
172 | LOGD("getName method value is %s", env->GetStringUTFChars(name, NULL));
173 |
174 | // 调用父类的其他方法
175 | animal_mid = env->GetMethodID(animal_cls, "callInstanceMethod", "(I)V");
176 | if (animal_mid == NULL) {
177 | return;
178 | }
179 | env->CallNonvirtualVoidMethod(cat, animal_cls, animal_mid);
180 |
181 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/local_and_global_references.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/4.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | /**
10 | * 使用局部引用来缓存static的变量,会导致出现野指针的情况
11 | */
12 | extern "C"
13 | JNIEXPORT jstring JNICALL
14 | Java_com_glumes_cppso_jnioperations_LocalAndGlobalReferenceOps_errorCacheUseLocalReference(
15 | JNIEnv *env, jobject instance) {
16 | static jmethodID mid = NULL;
17 | static jclass cls;
18 |
19 | // 局部引用不能使用 static 来缓存,否则函数退出后,自动释放,成为野指针,程序 Crash
20 | if (cls == NULL) {
21 | cls = env->FindClass("java/lang/String");
22 | if (cls == NULL) {
23 | return NULL;
24 | }
25 | } else {
26 | LOGD("cls is not null but program will crash");
27 | }
28 |
29 | if (mid == NULL) {
30 | mid = env->GetMethodID(cls, "", "([C)V");
31 | if (mid == NULL) {
32 | return NULL;
33 | }
34 | }
35 |
36 | jcharArray charEleArr = env->NewCharArray(10);
37 |
38 | const jchar *j_char = env->GetStringChars(env->NewStringUTF("LocalReference"), NULL);
39 |
40 | env->SetCharArrayRegion(charEleArr, 0, 10, j_char);
41 |
42 | jstring result = (jstring) env->NewObject(cls, mid, charEleArr);
43 |
44 | env->DeleteLocalRef(charEleArr);
45 |
46 | return result;
47 |
48 | }
49 |
50 | /**
51 | * 使用全局引用来缓存 static 的变量
52 | */
53 | extern "C"
54 | JNIEXPORT jstring JNICALL
55 | Java_com_glumes_cppso_jnioperations_LocalAndGlobalReferenceOps_cacheWithGlobalReference(JNIEnv *env,
56 | jobject instance) {
57 | static jclass stringClass = NULL;
58 | if (stringClass == NULL) {
59 | jclass localRefs = env->FindClass("java/lang/String");
60 | if (localRefs == NULL) {
61 | return NULL;
62 | }
63 | stringClass = (jclass) env->NewGlobalRef(localRefs);
64 | env->DeleteLocalRef(localRefs);
65 | if (stringClass == NULL) {
66 | return NULL;
67 | }
68 | } else {
69 | LOGD("use stringClass cached");
70 | }
71 |
72 | static jmethodID stringMid = NULL;
73 | if (stringMid == NULL) {
74 | stringMid = env->GetMethodID(stringClass, "", "(Ljava/lang/String;)V");
75 | if (stringMid == NULL) {
76 | return NULL;
77 | }
78 | } else {
79 | LOGD("use method cached");
80 | }
81 |
82 | jstring str = env->NewStringUTF("string");
83 | return (jstring) env->NewObject(stringClass, stringMid, str);
84 | }
85 |
86 |
87 | /**
88 | * 弱全局引用的使用,要防止弱全局引用在使用时被 GC 回收了
89 | */
90 | extern "C"
91 | JNIEXPORT void JNICALL
92 | Java_com_glumes_cppso_jnioperations_LocalAndGlobalReferenceOps_useWeakGlobalReference(JNIEnv *env,
93 | jobject instance) {
94 |
95 | static jclass stringClass = NULL;
96 | if (stringClass == NULL) {
97 | jclass localRefs = env->FindClass("java/lang/String");
98 | if (localRefs == NULL) {
99 | return;
100 | }
101 | stringClass = (jclass) env->NewWeakGlobalRef(localRefs);
102 | if (stringClass == NULL) {
103 | return;
104 | }
105 | }
106 | static jmethodID stringMid = NULL;
107 | if (stringMid == NULL) {
108 | stringMid = env->GetMethodID(stringClass, "", "(Ljava/lang/String;)V");
109 | if (stringMid == NULL) {
110 | return;
111 | }
112 | }
113 |
114 | jboolean isGC = env->IsSameObject(stringClass, NULL);
115 | if (isGC) {
116 | LOGD("weak reference has been gc");
117 | } else {
118 | jstring str = (jstring) env->NewObject(stringClass, stringMid,
119 | env->NewStringUTF("jstring"));
120 | LOGD("str is %s", env->GetStringUTFChars(str, NULL));
121 | }
122 | }
123 |
124 |
125 | /**
126 | * 使用 局部引用管理的一系列函数
127 | * 注释掉是因为暂时不能运行,未完善代码细节
128 | */
129 | extern "C"
130 | JNIEXPORT void JNICALL
131 | Java_com_glumes_cppso_jnioperations_LocalAndGlobalReferenceOps_useLocalReferenceManageFuntions(
132 | JNIEnv *env, jobject instance) {
133 |
134 | int len = 20;
135 | // Use EnsureLocalCapacity
136 | // if (env->EnsureLocalCapacity(len) < 0) {
137 | // // 创建失败,out of memory
138 | // }
139 | //
140 | // for (int i = 0; i < len; ++i) {
141 | // jstring jstr = env->GetObjectArrayElement(arr, i);
142 | // // 处理 字符串
143 | // // 创建了足够多的局部引用,这里就不用删除了,显然占用更多的内存
144 | // }
145 |
146 | // Use PushLocalFrame & PopLocalFrame
147 | // for (int i = 0; i < len; ++i) {
148 | // if (env->PushLocalFrame(len)) { // 创建指定数据的局部引用空间
149 | // //out ot memory
150 | // }
151 | // jstring jstr = env->GetObjectArrayElement(arr, i);
152 | // // 处理字符串
153 | // env->PopLocalFrame(NULL); // 直接释放这个空间内的所有局部引用
154 | // }
155 |
156 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/native_onload.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/28.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
9 |
10 | #define JAVA_CLASS "com/glumes/cppso/jnioperations/NativeOnLoadOps"
11 |
12 | jstring getMessage(JNIEnv *env, jobject jobj) {
13 | return env->NewStringUTF("this is msg");
14 | }
15 |
16 |
17 | jint nativePlus(JNIEnv *env, jobject jobj, jint x, jint y) {
18 | return x + y;
19 | }
20 |
21 |
22 | static JNINativeMethod gMethods[] = {
23 | {"getMessage", "()Ljava/lang/String;", (void *) getMessage},
24 | {"plus", "(II)I", (void *) nativePlus}
25 | };
26 |
27 |
28 | int registerNativeMethods(JNIEnv *env, const char *clsName, JNINativeMethod *gMethods, int numMethods) {
29 | jclass jcls;
30 | jcls = env->FindClass(clsName);
31 | if (jcls == NULL) {
32 | return JNI_FALSE;
33 | }
34 | if (env->RegisterNatives(jcls, gMethods, numMethods) < 0) {
35 | return JNI_FALSE;
36 | }
37 | return JNI_TRUE;
38 | }
39 |
40 | //
41 | //JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
42 | // JNIEnv *env;
43 | // if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
44 | // return JNI_ERR;
45 | // }
46 | //
47 | // registerNativeMethods(env, JAVA_CLASS, gMethods, NELEM(gMethods));
48 | //
49 | // LOGD("JNI OnLoad Call");
50 | //
51 | // return JNI_VERSION_1_6;
52 | //}
53 |
54 | JNIEXPORT void JNI_OnUnLoad(JavaVM *vm, void *reserved) {
55 | LOGD("JNI OnUnLoad Call");
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/string-type-operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/4/22.
3 | //
4 |
5 | #include
6 | #include
7 |
8 |
9 | #include
10 |
11 |
12 |
13 | /**
14 | * Java 传递 字符串到 Native,然后再从 Native 返回 字符串
15 | */
16 | extern "C"
17 | JNIEXPORT jstring JNICALL
18 | Java_com_glumes_cppso_jnioperations_StringTypeOps_getAndReleaseString(JNIEnv *env, jobject instance,
19 | jstring str_) {
20 | // Java 的字符串并不能直接转成 C/C++ 风格的字符串
21 | // 需要用到 GetStringChars 或者 GetStringUTFChars 相应的函数来申请内存
22 | // 转成一个指向 JVM 地址的指针
23 | // 最后还要释放该指针的内存
24 | const char *str = env->GetStringUTFChars(str_, 0);
25 | // GetStringUTFChars 涉及到申请内存,最好做个检查,防止 OOM
26 | // Get 和 Release 要配套使用,避免内存泄漏
27 | env->ReleaseStringUTFChars(str_, str);
28 |
29 | // 从 Native 返回字符串,将 C/C++ 风格的字符串返回到 Java 层
30 | // 也需要用到特定的函数来转换 NewStringUTF 或者 NewString 等
31 | const char *c_str = "this is C style string";
32 |
33 |
34 | // env->GetStringRegion()
35 |
36 | return env->NewStringUTF(c_str);
37 |
38 | }
39 |
40 | /**
41 | * 反转字符串操作
42 | */
43 | extern "C"
44 | JNIEXPORT jstring JNICALL
45 | Java_com_glumes_cppso_jnioperations_StringTypeOps_reverseString(JNIEnv *env, jobject instance,
46 | jstring str_) {
47 | const char *str = env->GetStringUTFChars(str_, 0);
48 |
49 | int length = env->GetStringLength(str_);
50 |
51 | char reverseString[length];
52 |
53 | for (int i = 0; i < length; ++i) {
54 | reverseString[i] = str[length - 1 - i];
55 | }
56 |
57 | env->ReleaseStringUTFChars(str_, str);
58 |
59 | // 此处的使用会引起崩溃,传入的字符串是 hello str 时
60 | return env->NewStringUTF(reverseString);
61 | }
62 |
63 |
64 | /**
65 | * 得到字符串一半内容,使用 GetStringRegion 方法
66 | */
67 | extern "C"
68 | JNIEXPORT jstring JNICALL
69 | Java_com_glumes_cppso_jnioperations_StringTypeOps_getHalfString(JNIEnv *env, jobject instance,
70 | jstring str_) {
71 | int len = env->GetStringLength(str_);
72 |
73 | jchar outputBuf[len / 2];
74 |
75 | // 截取一部分内容放到缓冲区里面去
76 | env->GetStringRegion(str_, 0, len / 2, outputBuf);
77 |
78 | // 再从缓冲区中得到 Java 字符串
79 | jstring ret = env->NewString(outputBuf, len / 2);
80 |
81 | return ret;
82 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/thread_operation.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/29.
3 | //
4 |
5 | #include
6 | #include "thread_operation.h"
7 | #include
8 |
9 | void *run(void *);
10 |
11 | void *printThreadHello(void *);
12 |
13 | static jmethodID printThreadName;
14 | static jmethodID printNativeMsg;
15 |
16 | static JavaVM *gVm = NULL;
17 | static jobject gObj = NULL;
18 | static pthread_mutex_t mutex;
19 | static const char *runtimeException = "java/lang/RuntimeException";
20 |
21 |
22 | JNIEXPORT int JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
23 | JNIEnv *env;
24 | if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
25 | return JNI_ERR;
26 | }
27 |
28 | gVm = vm;
29 |
30 | return JNI_VERSION_1_6;
31 | }
32 |
33 | JNIEXPORT void JNICALL
34 | Java_com_glumes_cppso_jnioperations_ThreadOps_nativeInit(JNIEnv *env, jobject jobj) {
35 | jclass jcls = env->GetObjectClass(jobj);
36 | printThreadName = env->GetMethodID(jcls, "printThreadName", "()V");
37 | printNativeMsg = env->GetMethodID(jcls, "printNativeMsg", "(Ljava/lang/String;)V");
38 | if (gObj == NULL) {
39 | gObj = env->NewGlobalRef(jobj);
40 | }
41 |
42 | // pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
43 | if (pthread_mutex_init(&mutex, NULL) != 0) {
44 | throwByName(env, runtimeException, "Unable to initialize mutex");
45 | }
46 | }
47 |
48 | JNIEXPORT void JNICALL
49 | Java_com_glumes_cppso_jnioperations_ThreadOps_nativeFree(JNIEnv *env, jobject) {
50 | if (gObj != NULL) {
51 | env->DeleteGlobalRef(gObj);
52 | gObj = NULL;
53 | }
54 | if (pthread_mutex_destroy(&mutex) != 0) {
55 | throwByName(env, runtimeException, "Unable to destroy mutex");
56 | }
57 | }
58 |
59 |
60 | JNIEXPORT void JNICALL
61 | Java_com_glumes_cppso_jnioperations_ThreadOps_createNativeThread(JNIEnv *, jobject) {
62 | pthread_t handles;
63 | int result = pthread_create(&handles, NULL, printThreadHello, NULL);
64 | if (result != 0) {
65 | LOGD("create thread failed");
66 | } else {
67 | LOGD("create thread success");
68 | }
69 | }
70 |
71 |
72 | JNIEXPORT void JNICALL
73 | Java_com_glumes_cppso_jnioperations_ThreadOps_posixThreads(JNIEnv *env, jobject jobj, jint num,
74 | jint iteration) {
75 | pthread_t *handles = new pthread_t[num];
76 |
77 | for (int i = 0; i < num; ++i) {
78 | pthread_t pthread;
79 |
80 | ThreadRunArgs *threadRunArgs = new ThreadRunArgs();
81 | threadRunArgs->id = i;
82 | threadRunArgs->result = i * i;
83 | // 创建一个线程,
84 | int result = pthread_create(&handles[i], NULL, run, (void *) threadRunArgs);
85 | if (result != 0) {
86 | throwByName(env, runtimeException, "Unable to create thread");
87 | }
88 | }
89 |
90 | for (int i = 0; i < num; ++i) {
91 | void *result = NULL;
92 | if (pthread_join(handles[i], &result) != 0) {
93 | throwByName(env, runtimeException, "Unable to join thread");
94 | } else {
95 | LOGD("return value is %d",result);
96 | char message[26];
97 | sprintf(message, "Worker %d returned %d", i, result);
98 | jstring msg = env->NewStringUTF(message);
99 | env->CallVoidMethod(gObj, printNativeMsg, msg);
100 | if (env->ExceptionOccurred() != NULL) {
101 | return;
102 | }
103 | }
104 | }
105 | }
106 |
107 |
108 | /**
109 | * 相当于 Thread 的 run 方法
110 | * @param args
111 | * @return
112 | */
113 | void *run(void *args) {
114 |
115 | JNIEnv *env = NULL;
116 | // 将当前线程添加到 Java 虚拟机上
117 | ThreadRunArgs *threadRunArgs = (ThreadRunArgs *) args;
118 |
119 | if (gVm->AttachCurrentThread(&env, NULL) == 0) {
120 |
121 | if (pthread_mutex_lock(&mutex) != 0) {
122 | throwByName(env, runtimeException, "Unable to lock mutex");
123 | }
124 |
125 | env->CallVoidMethod(gObj, printThreadName);
126 |
127 | if (pthread_mutex_unlock(&mutex)) {
128 | throwByName(env, runtimeException, "Unable to unlock mutex");
129 | }
130 | // 从 Java 虚拟机上分离当前线程
131 | gVm->DetachCurrentThread();
132 | }
133 | return (void *) threadRunArgs->result;
134 | }
135 |
136 |
137 | void *printThreadHello(void *) {
138 | LOGD("hello thread");
139 | return NULL;
140 | }
--------------------------------------------------------------------------------
/cppso/src/main/cpp/jnioperations/thread_operation.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by glumes on 2018/5/29.
3 | //
4 | #include
5 | #include
6 | #include
7 |
8 | #ifndef ANDROIDCPPSOLIB_THREAD_OPERATION_H
9 | #define ANDROIDCPPSOLIB_THREAD_OPERATION_H
10 |
11 |
12 | struct ThreadRunArgs {
13 | jint id;
14 | jint result;
15 | };
16 |
17 |
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 | /*
22 | * Class: com_glumes_cppso_jnioperations_ThreadOps
23 | * Method: nativeInit
24 | * Signature: ()V
25 | */
26 | JNIEXPORT void JNICALL Java_com_glumes_cppso_jnioperations_ThreadOps_nativeInit
27 | (JNIEnv *, jobject);
28 |
29 | /*
30 | * Class: com_glumes_cppso_jnioperations_ThreadOps
31 | * Method: nativeFree
32 | * Signature: ()V
33 | */
34 | JNIEXPORT void JNICALL Java_com_glumes_cppso_jnioperations_ThreadOps_nativeFree
35 | (JNIEnv *, jobject);
36 |
37 | /*
38 | * Class: com_glumes_cppso_jnioperations_ThreadOps
39 | * Method: nativeWorker
40 | * Signature: ()V
41 | */
42 | JNIEXPORT void JNICALL Java_com_glumes_cppso_jnioperations_ThreadOps_createNativeThread
43 | (JNIEnv *, jobject);
44 |
45 | /*
46 | * Class: com_glumes_cppso_jnioperations_ThreadOps
47 | * Method: posixThreads
48 | * Signature: (II)V
49 | */
50 | JNIEXPORT void JNICALL Java_com_glumes_cppso_jnioperations_ThreadOps_posixThreads
51 | (JNIEnv *, jobject, jint, jint);
52 |
53 | #ifdef __cplusplus
54 | }
55 | #endif
56 | #endif //ANDROIDCPPSOLIB_THREAD_OPERATION_H
57 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/aviplayer/AviPlayer.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.aviplayer;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | import java.io.IOException;
6 |
7 | /**
8 | * Created by glumes on 30/05/2018
9 | */
10 | public class AviPlayer {
11 |
12 |
13 | static {
14 | System.loadLibrary("aviplayer");
15 | }
16 |
17 | /**
18 | * 打开指定的 AVI 文件并且返回一个文件描述符
19 | *
20 | * @param fileName
21 | * @return
22 | * @throws IOException
23 | */
24 | public static native long open(String fileName) throws IOException;
25 |
26 | /**
27 | * 获得视频的宽度
28 | *
29 | * @param avi
30 | * @return
31 | */
32 | public static native int getWidth(long avi);
33 |
34 | /**
35 | * 获得视频的高度
36 | *
37 | * @param avi
38 | * @return
39 | */
40 | public static native int getHeight(long avi);
41 |
42 | /**
43 | * 获得帧速
44 | *
45 | * @param avi
46 | * @return
47 | */
48 | public static native double getFrameRate(long avi);
49 |
50 | /**
51 | * 基于给定的文件描述符关闭指定的 AVI 文件
52 | *
53 | * @param avi
54 | */
55 | public static native void close(long avi);
56 |
57 |
58 | public static native boolean render(long avi, Bitmap bitmap);
59 |
60 |
61 | public static native long init(long avi);
62 |
63 | public static native void initSurface(long instance, long avi);
64 |
65 | public static native boolean glRender(long instance, long avi);
66 |
67 | public static native void free(long instance);
68 |
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/infomanager/StudentInfoLoader.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.infomanager;
2 |
3 | /**
4 | * @Author glumes
5 | */
6 | public class StudentInfoLoader {
7 |
8 | static {
9 | System.loadLibrary("info-manger");
10 | }
11 |
12 | public static native void loadData();
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/ArrayTypeOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.model.Animal;
4 | import com.glumes.cppso.utils.LogUtil;
5 |
6 | /**
7 | * @Author glumes
8 | */
9 | public class ArrayTypeOps extends BaseOperation {
10 |
11 |
12 | @Override
13 | public void invoke() {
14 |
15 | int[] intArray = new int[]{1, 2, 3, 4, 5, 6};
16 | float[] floatArray = new float[]{1.0f, 2.0f, 3.0f};
17 | double[] doubleArray = new double[]{1.0, 2.0, 3.0};
18 | short[] shortArray = new short[]{1, 2, 3};
19 | long[] longArray = new long[]{1, 2, 3};
20 | boolean[] boolArray = new boolean[]{true, false, true};
21 | char[] charArray = new char[]{'a', 'b', 'c'};
22 | byte[] byteArray = new byte[]{2, 3, 4};
23 |
24 | primitiveTypeArray(intArray, floatArray, doubleArray, shortArray, longArray, boolArray, charArray, byteArray);
25 |
26 |
27 | Animal[] animals = new Animal[]{
28 | new Animal("cat"),
29 | new Animal("dog"),
30 | new Animal("pig"),
31 | new Animal("fish"),
32 | };
33 |
34 | print(
35 | intArraySum(intArray, 3)
36 | );
37 |
38 |
39 | for (Integer value : getIntArray(3)) {
40 | LogUtil.Companion.d("num is " + value);
41 | }
42 |
43 | // 对象数组的使用,相当于是一个一维数组,数组的每个内容都是一个数组
44 | int[][] data = getTwoDimensionalArray(3);
45 |
46 | for (int i = 0; i < 3; i++) {
47 | for (int j = 0; j < 3; j++) {
48 | LogUtil.Companion.d("data is " + data[i][j]);
49 | }
50 | }
51 |
52 | // 打印对象中的信息
53 | printAnimalsName(animals);
54 |
55 | }
56 |
57 |
58 | private native void primitiveTypeArray(int[] intArray,
59 | float[] floatArray,
60 | double[] doubleArray,
61 | short[] shortArray,
62 | long[] longArray,
63 | boolean[] boolArray,
64 | char[] charArray,
65 | byte[] byteArray);
66 |
67 | // Java 传递 数组 到 Native 进行数组求和
68 | private native int intArraySum(int[] intArray, int size);
69 |
70 | // 从 Native 返回基本数据类型数组
71 | private native int[] getIntArray(int num);
72 |
73 | // 从 Native 返回二维整型数组,相当于是一个一维整型数组,每个数组内容又是数组
74 | private native int[][] getTwoDimensionalArray(int size);
75 |
76 | private native void printAnimalsName(Animal[] animal);
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/BaseOperation.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.utils.LogUtil;
4 |
5 | /**
6 | * @Author glumes
7 | */
8 | abstract public class BaseOperation {
9 |
10 | static {
11 | System.loadLibrary("native-operation");
12 | }
13 |
14 | public abstract void invoke();
15 |
16 | public void print(Object... args) {
17 | if (args.length == 0) {
18 | return;
19 | }
20 |
21 | for (Object arg : args) {
22 | LogUtil.Companion.d("Java value is " + arg.toString() + "\n");
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/BasicTypeOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | /**
4 | * @Author glumes
5 | */
6 |
7 |
8 | /**
9 | * 基础数据类型的操作
10 | */
11 | public class BasicTypeOps extends BaseOperation {
12 |
13 |
14 | @Override
15 | public void invoke() {
16 |
17 | print(
18 | callNativeInt(100),
19 | callNativeByte((byte) 68),
20 | callNativeChar((char) 120),
21 | callNativeShort((short) 100),
22 | callNativeLong(1000),
23 | callNativeFloat((float) 1.0),
24 | callNativeDouble(100.0),
25 | callNativeBoolean(true)
26 |
27 | );
28 | }
29 |
30 | private native int callNativeInt(int num);
31 |
32 | private native byte callNativeByte(byte b);
33 |
34 | private native char callNativeChar(char ch);
35 |
36 | private native short callNativeShort(short sh);
37 |
38 | private native long callNativeLong(long l);
39 |
40 | private native float callNativeFloat(float f);
41 |
42 | private native double callNativeDouble(double d);
43 |
44 | private native boolean callNativeBoolean(boolean bool);
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/BitmapOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import android.graphics.Bitmap;
4 |
5 | /**
6 | * Created by glumes on 24/07/2018
7 | */
8 |
9 | public class BitmapOps extends BaseOperation {
10 |
11 | // 顺时针旋转 90° 的操作
12 | public native Bitmap rotateBitmap(Bitmap bitmap);
13 |
14 | public native Bitmap convertBitmap(Bitmap bitmap);
15 |
16 | public native Bitmap mirrorBitmap(Bitmap bitmap);
17 |
18 | @Override
19 | public void invoke() {
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/CacheFieldAndMethodOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.model.Animal;
4 | import com.glumes.cppso.utils.LogUtil;
5 |
6 | /**
7 | * @Author glumes
8 | */
9 | public class CacheFieldAndMethodOps extends BaseOperation {
10 |
11 | static {
12 | initCacheMethodId();
13 | }
14 |
15 | @Override
16 | public void invoke() {
17 | Animal animal = new Animal("Cache");
18 |
19 | staticCacheField(animal);
20 | LogUtil.Companion.d("name is " + animal.getName());
21 |
22 | callCacheMethod(animal);
23 |
24 | }
25 |
26 | private native void staticCacheField(Animal animal);
27 |
28 | private native void callCacheMethod(Animal animal);
29 |
30 | private static native void initCacheMethodId();
31 | }
32 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/ExceptionOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 |
4 | import android.util.Log;
5 |
6 | import com.glumes.cppso.utils.LogUtil;
7 |
8 | /**
9 | * @Author glumes
10 | */
11 | public class ExceptionOps extends BaseOperation {
12 |
13 | @Override
14 | public void invoke() {
15 |
16 | try {
17 | nativeThrowException();
18 | } catch (IllegalArgumentException e) {
19 | Log.e("NativeMethod", e.getMessage());
20 | }
21 |
22 | try {
23 | doit();
24 | } catch (Exception e) {
25 | LogUtil.Companion.d("In Java: " + e.getMessage());
26 | }
27 |
28 | nativeInvokeJavaException();
29 | }
30 |
31 | private native void doit() throws IllegalArgumentException;
32 |
33 | private native void nativeThrowException() throws IllegalArgumentException;
34 |
35 | /**
36 | * Native 代码调用 Java 时发生了异常,并不会处理
37 | */
38 | private native void nativeInvokeJavaException();
39 |
40 | /**
41 | * 由 Native 来调用该函数,由于 除数为 0 ,引发异常,在 Native 代码中清除这次异常
42 | *
43 | * @return
44 | */
45 | private int operation() {
46 | return 2 / 0;
47 | }
48 |
49 | /**
50 | * Native 调用 Java 方式时,导致异常了并不会立即终止 Native 方法的执行
51 | *
52 | * @throws NullPointerException
53 | */
54 | private void callback() throws NullPointerException {
55 | throw new NullPointerException("CatchThrow.callback by Native Code");
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/FieldAndMethodOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.model.Animal;
4 | import com.glumes.cppso.utils.LogUtil;
5 |
6 | /**
7 | * @Author glumes
8 | */
9 | public class FieldAndMethodOps extends BaseOperation {
10 |
11 |
12 | @Override
13 | public void invoke() {
14 | Animal animal = new Animal("cat");
15 |
16 | // 访问实例的字段
17 | accessInstanceFiled(animal);
18 |
19 | LogUtil.Companion.d("after access instance field,the name is " + animal.getName());
20 | // 访问静态类的字段
21 | accessStaticField(animal);
22 |
23 | LogUtil.Companion.d("after access static field,the num is " + Animal.num);
24 | // 访问实例的方法
25 | callInstanceMethod(animal);
26 | // 访问静态类的方法
27 | callStaticMethod(animal);
28 |
29 |
30 | }
31 |
32 | private native void accessInstanceFiled(Animal animal);
33 |
34 | private native void accessStaticField(Animal animal);
35 |
36 |
37 | private native void callInstanceMethod(Animal animal);
38 |
39 | private native void callStaticMethod(Animal animal);
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/InvokeConstructorOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.model.Animal;
4 | import com.glumes.cppso.utils.LogUtil;
5 |
6 | /**
7 | * @Author glumes
8 | */
9 | public class InvokeConstructorOps extends BaseOperation {
10 |
11 |
12 | @Override
13 | public void invoke() {
14 |
15 | print(
16 | invokeStringConstructors()
17 |
18 | );
19 |
20 | Animal animal = invokeAnimalConstructors();
21 | if (animal == null) {
22 | LogUtil.Companion.d("invoke animal constructor failed");
23 | } else {
24 | LogUtil.Companion.d("value is " + animal.getName());
25 | }
26 |
27 | animal = allocObjectConstructor();
28 |
29 | if (animal == null) {
30 | LogUtil.Companion.d("invoke animal constructor failed");
31 | } else {
32 | LogUtil.Companion.d("value is " + animal.getName());
33 | }
34 |
35 | callSuperMethod();
36 | }
37 |
38 | private native String invokeStringConstructors();
39 |
40 | private native Animal invokeAnimalConstructors();
41 |
42 | // 调用 allocObject 方法来构造一个类
43 | private native Animal allocObjectConstructor();
44 |
45 | // 调用父类的方法
46 | private native void callSuperMethod();
47 | }
48 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/LocalAndGlobalReferenceOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | /**
4 | * Created by glumes on 04/05/2018
5 | */
6 | public class LocalAndGlobalReferenceOps extends BaseOperation {
7 |
8 |
9 | @Override
10 | public void invoke() {
11 | // print(
12 | // cacheWithGlobalReference()
13 | // errorCacheUseLocalReference()
14 | // );
15 |
16 | useWeakGlobalReference();
17 | }
18 |
19 | private native void useWeakGlobalReference();
20 |
21 | private native String errorCacheUseLocalReference();
22 |
23 | // 全局引用
24 | private native String cacheWithGlobalReference();
25 |
26 | private native void useLocalReferenceManageFuntions();
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/NativeOnLoadOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.utils.LogUtil;
4 |
5 | /**
6 | * Created by glumes on 28/05/2018
7 | */
8 | public class NativeOnLoadOps extends BaseOperation {
9 |
10 |
11 | @Override
12 | public void invoke() {
13 | //
14 | // LogUtil.Companion.d("msg is " + getMessage());
15 | // LogUtil.Companion.d("plus result is " + plus(3, 0));
16 | }
17 |
18 |
19 | private native String getMessage();
20 |
21 | private native int plus(int x, int y);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/NoOperation.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.utils.LogUtil;
4 |
5 | /**
6 | * @Author glumes
7 | */
8 | public class NoOperation extends BaseOperation {
9 |
10 | @Override
11 | public void invoke() {
12 | LogUtil.Companion.d("invoke no operation");
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/OperationsFactory.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import android.util.SparseArray;
4 |
5 | import com.glumes.cppso.utils.ConstantsKt;
6 |
7 | /**
8 | * @Author glumes
9 | */
10 | public class OperationsFactory {
11 |
12 |
13 | private SparseArray mOperations = new SparseArray<>();
14 |
15 | private static class OperationsFactoryHolder {
16 | private static OperationsFactory mInstance = new OperationsFactory();
17 | }
18 |
19 | private OperationsFactory() {
20 |
21 | }
22 |
23 | public static OperationsFactory getInstance() {
24 | return OperationsFactoryHolder.mInstance;
25 | }
26 |
27 | public BaseOperation getOperations(int type) {
28 |
29 | BaseOperation ops = mOperations.get(type);
30 |
31 | if (ops != null) {
32 | return ops;
33 | }
34 |
35 | switch (type) {
36 | case ConstantsKt.NATIVE_BASIC_TYPE:
37 | ops = new BasicTypeOps();
38 | break;
39 | case ConstantsKt.NATIVE_STRING:
40 | ops = new StringTypeOps();
41 | break;
42 | case ConstantsKt.NATIVE_ARRAY:
43 | ops = new ArrayTypeOps();
44 | break;
45 | case ConstantsKt.NATIVE_FIELD_AND_METHOD:
46 | ops = new FieldAndMethodOps();
47 | break;
48 | case ConstantsKt.NATIVE_INVOKE_CONSTRUCTORS:
49 | ops = new InvokeConstructorOps();
50 | break;
51 | case ConstantsKt.NATIVE_CACHE_FIELD_AND_METHOD:
52 | ops = new CacheFieldAndMethodOps();
53 | break;
54 | case ConstantsKt.NATIVE_LOCAL_AND_GLOBAL_REFERENCES:
55 | ops = new LocalAndGlobalReferenceOps();
56 | break;
57 | case ConstantsKt.NATIVE_EXCEPTIONS_OPERATIONS:
58 | ops = new ExceptionOps();
59 | break;
60 | case ConstantsKt.NATIVE_ON_LOAD:
61 | ops = new NativeOnLoadOps();
62 | break;
63 | case ConstantsKt.NATIVE_THREAD_OPS:
64 | ops = new ThreadOps();
65 | break;
66 | default:
67 | break;
68 | }
69 |
70 | if (ops != null) {
71 | mOperations.put(type, ops);
72 | return mOperations.get(type);
73 | }
74 |
75 | // default operations
76 | return new NoOperation();
77 |
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/StringTypeOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 |
4 | /**
5 | * @Author glumes
6 | */
7 | public class StringTypeOps extends BaseOperation {
8 |
9 |
10 | @Override
11 | public void invoke() {
12 |
13 | String str = "hello";
14 |
15 | print(
16 | getAndReleaseString(str),
17 |
18 | reverseString(str),
19 |
20 | getHalfString(str)
21 |
22 | );
23 |
24 | }
25 |
26 |
27 | // Java 和 Native 字符串的相互转化
28 | private native String getAndReleaseString(String str);
29 |
30 | // 反转字符串操作
31 | private native String reverseString(String str);
32 |
33 | // 获得字符串一半内容
34 | private native String getHalfString(String str);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/jnioperations/ThreadOps.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.jnioperations;
2 |
3 | import com.glumes.cppso.utils.LogUtil;
4 |
5 | /**
6 | * Created by glumes on 28/05/2018
7 | */
8 | public class ThreadOps extends BaseOperation {
9 |
10 |
11 | @Override
12 | public void invoke() {
13 |
14 | createNativeThread();
15 | nativeInit();
16 | posixThreads(3, 3);
17 | }
18 |
19 | private native void createNativeThread();
20 |
21 | private native void nativeInit();
22 |
23 | private native void nativeFree();
24 |
25 | private native void posixThreads(int threads, int iterations);
26 |
27 | /**
28 | * 打印线程名称,并且模拟耗时任务
29 | */
30 | private void printThreadName() {
31 | LogUtil.Companion.d("print thread name current thread name is " + Thread.currentThread().getName());
32 | try {
33 | Thread.sleep(5000);
34 | } catch (InterruptedException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | /**
40 | * Native 回到到 Java 的方法,打印当前线程名字
41 | *
42 | * @param msg
43 | */
44 | private void printNativeMsg(String msg) {
45 | LogUtil.Companion.d("native msg is " + msg);
46 | LogUtil.Companion.d("print native msg current thread name is " + Thread.currentThread().getName());
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/model/Animal.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.model;
2 |
3 |
4 | import com.glumes.cppso.utils.LogUtil;
5 |
6 | /**
7 | * @Author glumes
8 | */
9 |
10 | public class Animal {
11 |
12 |
13 | protected String name;
14 |
15 | public static int num = 0;
16 |
17 | public Animal(String name) {
18 | this.name = name;
19 | }
20 |
21 |
22 | public String getName() {
23 | LogUtil.Companion.d("call getName method");
24 | return this.name;
25 | }
26 |
27 | public int getNum() {
28 | return num;
29 | }
30 |
31 | // C++ 调用 Java 的实例方法
32 | public void callInstanceMethod(int num) {
33 | LogUtil.Companion.d("call instance method and num is " + num);
34 | }
35 |
36 | // C++ 调用 Java 的类方法
37 | public static String callStaticMethod(String str) {
38 |
39 | if (str != null) {
40 | LogUtil.Companion.d("call static method with " + str);
41 | } else {
42 | LogUtil.Companion.d("call static method str is null");
43 | }
44 | return "";
45 | }
46 |
47 | public static String callStaticMethod(String[] strs, int num) {
48 | LogUtil.Companion.d("call static method with string array");
49 | if (strs != null) {
50 | for (String str : strs) {
51 | LogUtil.Companion.d("str in array is " + str);
52 | }
53 | }
54 | return "";
55 | }
56 |
57 | public static void callStaticVoidMethod() {
58 | LogUtil.Companion.d("call static void method");
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/model/Cat.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.model;
2 |
3 | import com.glumes.cppso.utils.LogUtil;
4 |
5 | /**
6 | * @Author glumes
7 | */
8 |
9 | public class Cat extends Animal {
10 |
11 |
12 | public Cat(String name) {
13 | super(name);
14 | LogUtil.Companion.d("Cat Construct call....");
15 | }
16 |
17 | @Override
18 | public String getName() {
19 | return "My name is " + this.name;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/utils/Constants.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.utils
2 |
3 | /**
4 | * Created by glumes on 28/02/2018
5 | */
6 |
7 |
8 | // 主页面的跳转
9 |
10 | const val JUMP_JNI_METHOD_ACTIVITY = 0x00
11 | const val JUMP_INFO_MANAGER_ACTIVITY = 0x01
12 | const val JUMP_GRAPHIC_API_ACTIVITY = 0x02
13 | const val JUMP_BITMAP_OPERATION_ACTIVITY = 0x03
14 |
15 | // JNI 操作相关
16 |
17 | const val NO_NATIVE_OPERATION = 0x10
18 | const val NATIVE_BASIC_TYPE = 0x13
19 | const val NATIVE_STRING = 0x11
20 | const val NATIVE_ARRAY = 0x12
21 |
22 | const val NATIVE_FIELD_AND_METHOD = 0x17
23 |
24 | const val NATIVE_CACHE_FIELD_AND_METHOD = 0x18
25 |
26 | const val NATIVE_INVOKE_CONSTRUCTORS = 0x19
27 |
28 | const val NATIVE_LOCAL_AND_GLOBAL_REFERENCES = 0x1a
29 |
30 | const val NATIVE_EXCEPTIONS_OPERATIONS = 0x1b
31 |
32 | const val NATIVE_ON_LOAD = 0x1c
33 |
34 | const val NATIVE_THREAD_OPS = 0x1d
35 |
36 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com/glumes/cppso/utils/LogUtil.kt:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso.utils
2 |
3 | import android.util.Log
4 |
5 | /**
6 | * Created by glumes on 28/02/2018
7 | */
8 | class LogUtil {
9 |
10 | companion object {
11 |
12 | var TAG: String = "NativeMethod"
13 |
14 | fun d(msg: String) {
15 | d(msg, tag = TAG)
16 | }
17 |
18 | fun d(msg: String, tag: String = TAG) {
19 | Log.d(tag, msg)
20 | }
21 |
22 | fun i(msg: String) {
23 | i(msg, tag = TAG)
24 | }
25 |
26 | fun i(msg: String, tag: String = TAG) {
27 | Log.i(tag, msg)
28 | }
29 |
30 | fun e(msg: String) {
31 | e(msg, tag = TAG)
32 | }
33 |
34 | fun e(msg: String, tag: String = TAG) {
35 | Log.e(tag, msg)
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/cppso/src/main/java/com_glumes_cppso_aviplayer_AviPlayer.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class com_glumes_cppso_aviplayer_AviPlayer */
4 |
5 | #ifndef _Included_com_glumes_cppso_aviplayer_AviPlayer
6 | #define _Included_com_glumes_cppso_aviplayer_AviPlayer
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 | /*
11 | * Class: com_glumes_cppso_aviplayer_AviPlayer
12 | * Method: open
13 | * Signature: (Ljava/lang/String;)J
14 | */
15 | JNIEXPORT jlong JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_open
16 | (JNIEnv *, jclass, jstring);
17 |
18 | /*
19 | * Class: com_glumes_cppso_aviplayer_AviPlayer
20 | * Method: getWidth
21 | * Signature: (J)I
22 | */
23 | JNIEXPORT jint JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getWidth
24 | (JNIEnv *, jclass, jlong);
25 |
26 | /*
27 | * Class: com_glumes_cppso_aviplayer_AviPlayer
28 | * Method: getHeight
29 | * Signature: (J)I
30 | */
31 | JNIEXPORT jint JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getHeight
32 | (JNIEnv *, jclass, jlong);
33 |
34 | /*
35 | * Class: com_glumes_cppso_aviplayer_AviPlayer
36 | * Method: getFrameRate
37 | * Signature: (J)D
38 | */
39 | JNIEXPORT jdouble JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_getFrameRate
40 | (JNIEnv *, jclass, jlong);
41 |
42 | /*
43 | * Class: com_glumes_cppso_aviplayer_AviPlayer
44 | * Method: close
45 | * Signature: (J)V
46 | */
47 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_close
48 | (JNIEnv *, jclass, jlong);
49 |
50 | /*
51 | * Class: com_glumes_cppso_aviplayer_AviPlayer
52 | * Method: render
53 | * Signature: (JLandroid/graphics/Bitmap;)Z
54 | */
55 | JNIEXPORT jboolean JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_render
56 | (JNIEnv *, jclass, jlong, jobject);
57 |
58 | /*
59 | * Class: com_glumes_cppso_aviplayer_AviPlayer
60 | * Method: init
61 | * Signature: (J)J
62 | */
63 | JNIEXPORT jlong JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_init
64 | (JNIEnv *, jclass, jlong);
65 |
66 | /*
67 | * Class: com_glumes_cppso_aviplayer_AviPlayer
68 | * Method: initSurface
69 | * Signature: (JJ)V
70 | */
71 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_initSurface
72 | (JNIEnv *, jclass, jlong, jlong);
73 |
74 | /*
75 | * Class: com_glumes_cppso_aviplayer_AviPlayer
76 | * Method: glRender
77 | * Signature: (JJ)Z
78 | */
79 | JNIEXPORT jboolean JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_glRender
80 | (JNIEnv *, jclass, jlong, jlong);
81 |
82 | /*
83 | * Class: com_glumes_cppso_aviplayer_AviPlayer
84 | * Method: free
85 | * Signature: (J)V
86 | */
87 | JNIEXPORT void JNICALL Java_com_glumes_cppso_aviplayer_AviPlayer_free
88 | (JNIEnv *, jclass, jlong);
89 |
90 | #ifdef __cplusplus
91 | }
92 | #endif
93 | #endif
94 |
--------------------------------------------------------------------------------
/cppso/src/main/java/com_glumes_cppso_jnioperations_BitmapOps.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class com_glumes_cppso_jnioperations_BitmapOps */
4 |
5 | #ifndef _Included_com_glumes_cppso_jnioperations_BitmapOps
6 | #define _Included_com_glumes_cppso_jnioperations_BitmapOps
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 | /*
11 | * Class: com_glumes_cppso_jnioperations_BitmapOps
12 | * Method: rotateBitmap
13 | * Signature: (Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap;
14 | */
15 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_rotateBitmap
16 | (JNIEnv *, jobject, jobject);
17 |
18 | /*
19 | * Class: com_glumes_cppso_jnioperations_BitmapOps
20 | * Method: convertBitmap
21 | * Signature: (Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap;
22 | */
23 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_convertBitmap
24 | (JNIEnv *, jobject, jobject);
25 |
26 | /*
27 | * Class: com_glumes_cppso_jnioperations_BitmapOps
28 | * Method: mirrorBitmap
29 | * Signature: (Landroid/graphics/Bitmap;)Landroid/graphics/Bitmap;
30 | */
31 | JNIEXPORT jobject JNICALL Java_com_glumes_cppso_jnioperations_BitmapOps_mirrorBitmap
32 | (JNIEnv *, jobject, jobject);
33 |
34 | #ifdef __cplusplus
35 | }
36 | #endif
37 | #endif
38 |
--------------------------------------------------------------------------------
/cppso/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | cppso
3 |
4 |
--------------------------------------------------------------------------------
/cppso/src/test/java/com/glumes/cppso/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.glumes.cppso;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
19 | android.enableAapt2=true
20 | android.databinding.enableV2=true
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':cppso'
2 |
--------------------------------------------------------------------------------