Implementing Android.bp for generating shared library - android

Consider the following files :
abc.c
#ifdef MY_FLAG
#include <stdio.h>
int main() {
printf("hello world\n");
}
#endif
Android.bp
cc_defaults {
name: "my_defaults_1",
srcs: ["abc.c"],
}
cc_defaults {
name: "my_defaults_2",
defaults: ["my_defaults_1"],
cflags: ["-DMY_FLAG"],
}
cc_library_shared {
name: "my_library",
defaults: ["my_defaults_2"],
}
Here my question is, where do i need to define my flag(MY_FLAG) in order to get that file executed and getting print, is it in my_defaults_1 or my_defaults_2 or defining in any one of these, will cause same result? Because when i defined the flag in my_defaults_2 i didn't got the print.

Related

How to append aapt flags to Android.bp dynamically

I need to dynamically append new flags to aaptflags property from android_app from Android.bp, based in some conditions.
I am trying something similar to this answer, the Go script is executed (I can see it when I add some prints), but the flags are not added.
This is my code, any idea what I'm missing?
my_defaults.go
package my_defaults
import (
"android/soong/android"
"android/soong/cc"
)
func aaptFlags(ctx android.BaseContext) []string {
// I will replace this with some logic.
// Returning a fixed value just for sake of simplicity
var cflags []string
cflags = append(cflags, "my_flag_here")
return cflags
}
func myDefaults(ctx android.LoadHookContext) {
type props struct {
aaptflags []string
}
p := &props{}
p.aaptflags = aaptFlags(ctx)
ctx.AppendProperties(p)
}
func init() {
android.RegisterModuleType("my_defaults", myDefaultsFactory)
}
func myDefaultsFactory() android.Module {
module := cc.DefaultsFactory()
android.AddLoadHook(module, myDefaults)
return module
}
Android.bp
bootstrap_go_package {
name: "soong-my_defaults",
pkgPath: "android/soong/my/defaults",
deps: [
"soong",
"soong-android",
"soong-cc"
],
srcs: [
"my_defaults.go"
],
pluginFor: ["soong_build"]
}
my_defaults {
name: "my_defaults",
}
android_app {
name: "MyApp",
defaults: [
"my_defaults",
],
srcs: ["src/**/*.java"],
// I need dinamically append new flags here
aaptflags: [
"some_flags",
],
// ...
}
// ...
Thanks
Probably the problem is with the custom field's name - it is in lower case, which in go means it is a private field. As I see, all fields in the referenced example are capitalized.

Rust JNI async callback with Tokio and Reqwest for Android

I'm testing Rust with JNI async execution. I want to do execute requests in Rust and return the result to Android asynchronously with callback. I'm testing code to execute the request in the command line and it works fine.
That is how it works on command line:
Callback struck:
struct Processor {
pub(crate) callback: Box<dyn FnMut(String)>,
}
impl Processor {
fn set_callback(&mut self, c: impl FnMut(String) + 'static) {
self.callback = Box::new(c);
}
fn process_events(&mut self, result: String) {
(self.callback)(result);
}
}
Tokio/reqwest:
const DATA_URL: &str = "https://pokeapi.co/api/v2/pokemon/1/";
#[tokio::main]
pub async fn load_swapi_async_with_cb(callback: Box<dyn FnMut(String)>) -> Result<(), Box<dyn std::error::Error>> {
println!("load_swload_swapi_async_with_cbapi_async started");
let mut cb = Processor {
callback: Box::new(callback),
};
let body = reqwest::get(DATA_URL)
.await?
.json::<HashMap<String, String>>()
.await?;
//println!("{:#?}", body);
let name = match body.get("name") {
Some(name) => name,
None => "Failed to parse"
}.to_string();
println!("Name is: {} ", name);
cb.process_events(name);
Ok(())
}
And JNI part:
#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn Java_com_omg_app_greetings_MainActivity_callback(env: JNIEnv,
_class: JClass,
callback: JObject) {
static callback: dyn FnMut(String) + 'static = |name| {
let response = env.new_string(&name).expect("Couldn't create java string!");
env.call_method(callback, "rustCallbackResult", "(Ljava/lang/String;)V",
&[JValue::from(JObject::from(response))]).unwrap();
};
pokemon_api(callback);
}
And pokemon API method:
#[no_mangle]
pub extern fn pokemon_api(callback: impl FnMut(String) + 'static) {
let cb_box = Box::new(callback);
swapi::load_swapi_async_with_cb(cb_box);
}
The error I'm facing:
JNI ENV env non-constant value:
let response = env.new_string(&name).expect("Couldn't create java string!");
| ^^^ non-constant value
callback - doesn't have a size known at compile-time:
static callback: dyn FnMut(String) + 'static = |name| {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
I was checking how this working, but example seems to be out of date:
* https://github.com/mozilla/rust-android-gradle/blob/master/samples/rust/src/lib.rs
I fixed with my problem with the usage of the https://github.com/Dushistov/rust_swig
After you integrate it, it will autogenerate code and you can check how it does it.

How do I add condition in Android.bp

I want to differentiate code between Android Q and Android R how do I achieve this in Android.bp?
In Android.mk I did something like this
ifeq ($(PLATFORM_VERSION), R)
LOCAL_CFLAGS += -DANDROID_R_AOSP
else
LOCAL_CFLAGS += -DANDROID_Q_AOSP
How to do above code in Android.bp?
Follow the instructions given here.
Replace this part in the my_defaults.go:
if ctx.AConfig().Getenv("SOME_ENV_VAR") == "some_value" {
cflags = append(cflags, "-DCONDITIONAL")
}
With:
if ctx.AConfig().PlatformVersionName() == "R" {
cflags = append(cflags, "-DANDROID_R_AOSP")
} else {
cflags = append(cflags, "-DANDROID_Q_AOSP")
}
Reference: link. In older versions this function was called PlatformVersion() (link), but for Android 9 or higher you should be fine.
GO
You can write a go script with your conditions. Follow
Is there a way to add/remove module in Android.bp?
What is art.go? And why is it considered a way to write conditionals in bp files?
Conditional compilation
If you just want to include a module conditionally you can define many Android.bp modules and include them based on conditions in Android.mk files.
https://android.googlesource.com/platform/build/soong/+/HEAD/docs/best_practices.md#removing-conditionals
soong_config_modules
You will face parsing errors if any of your Android.bp files include libraries not supported by your AOSP.
To fix that you can use soong_config_modules. Note that this is supported only Android 11 R onwards.
Details are given in https://android.googlesource.com/platform/build/soong/+/refs/heads/master/android/soong_config_modules.go
However, I'll give you an example.
Here I am including special libraries when the AOSP is Android 12. Since these libraries might not be present on lower versions, I will not include iot-camera-system.mk in PRODUCT_PACKAGES so it will not be included as a preinstalled app.
What specifically I will achieve with soong_config_modules is removal of parsing errors when these libraries are not present (Android parses all Android.bp files to form a parse tree, it also checks for the existence of their dependencies and build fails when they are not present).
iot-camera-system.mk
# CameraApp Android Application Package
ifeq ($(PLATFORM_VERSION), $(filter $(PLATFORM_VERSION),S 12))
PRODUCT_PACKAGES += CameraApp
SOONG_CONFIG_NAMESPACES += camera
SOONG_CONFIG_camera += camtargets
SOONG_CONFIG_camera_camtargets := newCameraTarget
else
SOONG_CONFIG_NAMESPACES += camera
SOONG_CONFIG_camera += camtargets
SOONG_CONFIG_camera_camtargets := oldCameraTarget
endif
Android.bp
// This introduces the module type camera_cc_defaults
// If target.mk file contained:
//
// SOONG_CONFIG_NAMESPACES += camera
// SOONG_CONFIG_camera += camtargets
// SOONG_CONFIG_camera_camtargets := newCameraTarget
//
// Then our libs would build with static_libs
soong_config_module_type {
name: "camera_cc_defaults",
module_type: "cc_defaults",
config_namespace: "camera",
variables: ["camtargets"],
properties: ["static_libs"],
}
soong_config_string_variable {
name: "camtargets",
values: ["oldCameraTarget", "newCameraTarget"],
}
camera_cc_defaults {
name: "camera_defaults",
soong_config_variables: {
camtargets: {
oldCameraTarget: {
static_libs: [
],
},
newCameraTarget: {
static_libs: [
"androidx.core_core-ktx",
"androidx.fragment_fragment-ktx",
"androidx.navigation_navigation-fragment-ktx",
"androidx.navigation_navigation-ui-ktx",
"androidx.lifecycle_lifecycle-runtime-ktx",
"kotlinx_coroutines",
"kotlinx_coroutines_android",
],
},
},
},
}
android_library {
name: "utils",
defaults: ["camera_defaults"],
manifest: "utils/src/main/AndroidManifest.xml",
platform_apis: true,
srcs: [
"utils/src/main/java/com/example/android/camera/utils/*.kt",
],
resource_dirs: [
"utils/src/main/res/",
],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"androidx.localbroadcastmanager_localbroadcastmanager",
"com.google.android.material_material",
"androidx.exifinterface_exifinterface",
"androidx.core_core",
"androidx.preference_preference",
"androidx.fragment_fragment",
"androidx.recyclerview_recyclerview",
"androidx.lifecycle_lifecycle-runtime",
"androidx.lifecycle_lifecycle-extensions",
"kotlin-stdlib",
"kotlin-reflect",
"gson-prebuilt-jar",
],
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
}
android_app {
name: "CameraApp",
defaults: ["camera_defaults"],
manifest: "app/src/main/AndroidManifest.xml",
privileged: true,
platform_apis: true,
certificate: "platform",
srcs: [
"app/src/main/java/com/example/android/camera2/video/*.kt",
"app/src/main/java/com/example/android/camera2/video/fragments/*.kt",
"app/src/main/java/com/example/android/camera2/video/overlay/*.kt",
],
resource_dirs: [
"app/src/main/res/",
],
static_libs: [
"androidx-constraintlayout_constraintlayout",
"androidx.appcompat_appcompat",
"androidx.localbroadcastmanager_localbroadcastmanager",
"com.google.android.material_material",
"androidx.exifinterface_exifinterface",
"androidx.core_core",
"androidx.preference_preference",
"androidx.fragment_fragment",
"androidx.recyclerview_recyclerview",
"androidx.lifecycle_lifecycle-runtime",
"androidx.lifecycle_lifecycle-extensions",
"kotlin-stdlib",
"kotlin-reflect",
"gson-prebuilt-jar",
"utils",
],
optimize: {
enabled: false,
},
dex_preopt: {
enabled: false,
},
}

Qt QBS and android

I'm trying to find a simple tutorial: how to make a simple application for android using gbps. The following links were found:
Stack oferflow. The answer to this question has not been
received, although the version of the cbs has already been updated
to 1.11 and the support of android is included.
AndroidApk Item in QBS Documentation. In this case I get warning: '../Application/src/main/AndroidManifest.xml' does not exist.
I unfortunately could not find any new information. I ask for help.
Update:
For Qmake I just create standard widget project like this one:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = androidtest
TEMPLATE = app
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
CONFIG += mobility
MOBILITY =
And this is works and builds fine. QtCreator automatically create all necessary files and than run app on my phone
In Qbs I try to make same application. For this reason I have QBS-file:
import qbs
Project {
CppApplication {
name: "helloworld"
Depends {
name: "Qt"
submodules: [
"core",
"widgets"
]
}
Depends { name: "Android.ndk" }
Android.ndk.appStl: "gnustl_shared"
Group {
name: "src"
files: [
"main*.*"
]
}
}
AndroidApk {
name: "helloworld_android"
Depends {name: "helloworld" }
packageName: "com.example.android.helloworld"
}
}
At the end I have Done with HelloWorld product (libhelloworld.so). But first error of "helloworld_android" is a fail at android manifest. This file is undefined. What I should do next?
qmake has some built-in magic when building for Android, like using resources provided by Qt (including a manifest template) and running the android-deployqt tool. None of this is currently done by qbs.
Ok, I think I made it. It's not a good solution but this is work. Resulting APK you can find in "\install-root\$productName$\build\outputs\apk\$productName$-debug.apk
import qbs
import qbs.TextFile
import qbs.Process
import qbs.File
Project {
//Main Application
CppApplication {
name: "helloworld";
Depends {
name: "Qt"
submodules: [
"core",
"widgets"
]
}
Depends { name: "Android.ndk" }
Android.ndk.appStl: "gnustl_shared"
Group {
name: "src"
files: [
"main*.*"
]
}
Group {
qbs.install: true
fileTagsFilter: "dynamiclibrary"
qbs.installPrefix : product.name+"/libs/"+Android.ndk.abi+"/"
}
}
//Preparation
Product {
name: "Prepared2Deploy"
type: "prepared2deploy"
Depends { name: "helloworld" }
Depends { name: "Qt.core" }
Depends { name: "Android.ndk" }
Depends { name: "Android.sdk" }
Rule {
inputsFromDependencies: "installable"
Artifact {
filePath: input.fileName+".json"
fileTags: "prepared2deploy"
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "prepare for androidDeployQt";
cmd.highlight = "install";
cmd.sourceCode = function() {
var outputFile = new TextFile(output.filePath, TextFile.WriteOnly);
outputFile.writeLine("{");
outputFile.writeLine(" \"qt\": \"" + product.Qt.core.binPath.replace(/\/bin$/,"") + "\",");
outputFile.writeLine(" \"sdk\": \"" + product.Android.sdk.sdkDir + "\",");
outputFile.writeLine(" \"sdkBuildToolsRevision\": \"" + product.Android.sdk.buildToolsVersion + "\",");
var ndkDir = product.Android.ndk.ndkDir.replace(/\\/g,"/"); //why sdk ndk get wrong slashes?
outputFile.writeLine(" \"ndk\": \""+ndkDir+"\",");
var toolchain = product.cpp.toolchainPrefix.replace(/-$/,"");
outputFile.writeLine(" \"toolchain-prefix\": \"" + toolchain + "\",");
outputFile.writeLine(" \"tool-prefix\": \"" + toolchain + "\",");
outputFile.writeLine(" \"toolchain-version\": \"4.9\","); //how I can get it ???
outputFile.writeLine(" \"ndk-host\": \"windows-x86_64\","); //how I can get it ???
var abi = product.Android.ndk.abi
outputFile.writeLine(" \"target-architecture\": \""+abi+"\",");
outputFile.writeLine(" \"stdcpp-path\": \""+ndkDir+"/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + //how I can get it ???
abi+"/lib"+product.Android.ndk.appStl+".so\",");
outputFile.writeLine(" \"application-binary\": \""+ input.filePath+"\"");
outputFile.writeLine("}");
outputFile.close();
}
return cmd;
}
}
}
//Deployer
Product {
name: "AndroidDeployQt"
Depends { name: "helloworld" }
id: androidDeployQt
type: "androidDeployQt"
Depends {name: "Qt.core" }
Rule {
inputsFromDependencies: "prepared2deploy"
alwaysRun: true
Artifact {
filePath: "log.txt"
fileTags: "androidDeployQt"
}
prepare: {
var cmd = new JavaScriptCommand();
cmd.description = "androidDeployQt";
cmd.highlight = "install";
cmd.sourceCode = function() {
var logFile = new TextFile(output.filePath, TextFile.WriteOnly);
logFile.writeLine(input.fileName);
var productName = input.fileName.replace(/.so.json$/,"").replace(/^(lib)/,"");
var androidDeployProcess = new Process();
var exitCode = androidDeployProcess.exec(product.Qt.core.binPath+"/androiddeployqt.exe",
[
"--input", input.filePath,
"--output", project.buildDirectory+"/install-root/"+productName,
"--android-platform", "android-25", //???
"--gradle"
])
if (exitCode) {
console.error("Error at androidDeployProcess. Error code: "+exitCode);
console.error(androidDeployProcess.readStdErr());
console.error("FULL_LOG: ");
console.error(androidDeployProcess.readStdOut());
}
logFile.close();
}
return cmd;
}
}
}
}
QBS 1.13, released on February this year (2019) makes deploying an Android application as simple as with qmake. In practice, you don't need to do anything special. For example, I took the contactlist application from the Qt examples and added this QBS file:
import qbs 1.0
Project {
QtGuiApplication {
name: "contactlist"
install: true
files: [
"contactmodel.h",
"contactmodel.cpp",
"main.cpp",
]
Group {
files: [
"*.qml",
"designer/Backend/*.qml",
"designer/Backend/qmldir",
]
fileTags: ["qt.core.resource_data"]
}
Depends { name: "Qt.quick" }
}
}
As you can see, there's nothing specific to Android here. The only trick I'm using is to assign the tag qt.core.resource_data to the QML files in order to have them compiled as resource files — but it's not even required.
With qbs run the application will be run in your connected Android device.

Migrating Eclipse android project with NDK and Gstreamer usage to Android Studio

I have a perfectly working android project in Eclipse, the project includes NDK support and uses Gstreamer.
When I migrate the project from Eclipse to Android Studio all sorts of problems pop up, and I just cant successfully compile the project.
I did a thorough research on each and every error I've encountered but still couldn't compile and run the project on android studio.
https://drive.google.com/file/d/0B_euzgSjTAqcQngwbzR1cXY0MkU/view?usp=sharing
A link to the working Eclipse project, I hope someone could direct me on the right way.
This is the import summary:
ECLIPSE ANDROID PROJECT IMPORT SUMMARY
Ignored Files:
The following files were not copied into the new Gradle project; you
should evaluate whether these are still needed in your project and if
so manually move them:
.externalToolBuilders\
.externalToolBuilders\Wiz.launch
gst-build\
gst-build\gstreamer_android.c
gst-build\gstreamer_android.o
Replaced Jars with Dependencies:
The importer recognized the following .jar files as third party
libraries and replaced them with Gradle dependencies instead. This has
the advantage that more explicit version information is known, and the
libraries can be updated automatically. However, it is possible that
the .jar file in your project was of an older version than the
dependency we picked, which could render the project not compileable.
You can disable the jar replacement in the import wizard and try again:
android-support-v4.jar => com.android.support:support-v4:23.3.0
Moved Files:
Android Gradle projects use a different directory structure than ADT
Eclipse projects. Here's how the projects were restructured:
AndroidManifest.xml => app\src\main\AndroidManifest.xml
assets\ => app\src\main\assets\
jni\ => app\src\main\jni\
libs\armeabi\libavcodec.so => app\src\main\jniLibs\armeabi\libavcodec.so
libs\armeabi\libavdevice.so => app\src\main\jniLibs\armeabi\libavdevice.so
libs\armeabi\libavfilter.so => app\src\main\jniLibs\armeabi\libavfilter.so
libs\armeabi\libavformat.so => app\src\main\jniLibs\armeabi\libavformat.so
libs\armeabi\libavutil.so => app\src\main\jniLibs\armeabi\libavutil.so
libs\armeabi\libgstreamer_android.so => app\src\main\jniLibs\armeabi\libgstreamer_android.so
libs\armeabi\libjniARToolKitPlus.so => app\src\main\jniLibs\armeabi\libjniARToolKitPlus.so
libs\armeabi\libjniavcodec.so => app\src\main\jniLibs\armeabi\libjniavcodec.so
libs\armeabi\libjniavdevice.so => app\src\main\jniLibs\armeabi\libjniavdevice.so
libs\armeabi\libjniavfilter.so => app\src\main\jniLibs\armeabi\libjniavfilter.so
libs\armeabi\libjniavformat.so => app\src\main\jniLibs\armeabi\libjniavformat.so
libs\armeabi\libjniavutil.so => app\src\main\jniLibs\armeabi\libjniavutil.so
libs\armeabi\libjnicvkernels.so => app\src\main\jniLibs\armeabi\libjnicvkernels.so
libs\armeabi\libjniopencv_calib3d.so => app\src\main\jniLibs\armeabi\libjniopencv_calib3d.so
libs\armeabi\libjniopencv_contrib.so => app\src\main\jniLibs\armeabi\libjniopencv_contrib.so
libs\armeabi\libjniopencv_core.so => app\src\main\jniLibs\armeabi\libjniopencv_core.so
libs\armeabi\libjniopencv_features2d.so => app\src\main\jniLibs\armeabi\libjniopencv_features2d.so
libs\armeabi\libjniopencv_flann.so => app\src\main\jniLibs\armeabi\libjniopencv_flann.so
libs\armeabi\libjniopencv_highgui.so => app\src\main\jniLibs\armeabi\libjniopencv_highgui.so
libs\armeabi\libjniopencv_imgproc.so => app\src\main\jniLibs\armeabi\libjniopencv_imgproc.so
libs\armeabi\libjniopencv_legacy.so => app\src\main\jniLibs\armeabi\libjniopencv_legacy.so
libs\armeabi\libjniopencv_ml.so => app\src\main\jniLibs\armeabi\libjniopencv_ml.so
libs\armeabi\libjniopencv_nonfree.so => app\src\main\jniLibs\armeabi\libjniopencv_nonfree.so
libs\armeabi\libjniopencv_objdetect.so => app\src\main\jniLibs\armeabi\libjniopencv_objdetect.so
libs\armeabi\libjniopencv_photo.so => app\src\main\jniLibs\armeabi\libjniopencv_photo.so
libs\armeabi\libjniopencv_stitching.so => app\src\main\jniLibs\armeabi\libjniopencv_stitching.so
libs\armeabi\libjniopencv_video.so => app\src\main\jniLibs\armeabi\libjniopencv_video.so
libs\armeabi\libjniopencv_videostab.so => app\src\main\jniLibs\armeabi\libjniopencv_videostab.so
libs\armeabi\libjnipostproc.so => app\src\main\jniLibs\armeabi\libjnipostproc.so
libs\armeabi\libjniswresample.so => app\src\main\jniLibs\armeabi\libjniswresample.so
libs\armeabi\libjniswscale.so => app\src\main\jniLibs\armeabi\libjniswscale.so
libs\armeabi\libopencv_calib3d.so => app\src\main\jniLibs\armeabi\libopencv_calib3d.so
libs\armeabi\libopencv_contrib.so => app\src\main\jniLibs\armeabi\libopencv_contrib.so
libs\armeabi\libopencv_core.so => app\src\main\jniLibs\armeabi\libopencv_core.so
libs\armeabi\libopencv_features2d.so => app\src\main\jniLibs\armeabi\libopencv_features2d.so
libs\armeabi\libopencv_flann.so => app\src\main\jniLibs\armeabi\libopencv_flann.so
libs\armeabi\libopencv_highgui.so => app\src\main\jniLibs\armeabi\libopencv_highgui.so
libs\armeabi\libopencv_imgproc.so => app\src\main\jniLibs\armeabi\libopencv_imgproc.so
libs\armeabi\libopencv_info.so => app\src\main\jniLibs\armeabi\libopencv_info.so
libs\armeabi\libopencv_legacy.so => app\src\main\jniLibs\armeabi\libopencv_legacy.so
libs\armeabi\libopencv_ml.so => app\src\main\jniLibs\armeabi\libopencv_ml.so
libs\armeabi\libopencv_nonfree.so => app\src\main\jniLibs\armeabi\libopencv_nonfree.so
libs\armeabi\libopencv_objdetect.so => app\src\main\jniLibs\armeabi\libopencv_objdetect.so
libs\armeabi\libopencv_photo.so => app\src\main\jniLibs\armeabi\libopencv_photo.so
libs\armeabi\libopencv_stitching.so => app\src\main\jniLibs\armeabi\libopencv_stitching.so
libs\armeabi\libopencv_ts.so => app\src\main\jniLibs\armeabi\libopencv_ts.so
libs\armeabi\libopencv_video.so => app\src\main\jniLibs\armeabi\libopencv_video.so
libs\armeabi\libopencv_videostab.so => app\src\main\jniLibs\armeabi\libopencv_videostab.so
libs\armeabi\libpostproc.so => app\src\main\jniLibs\armeabi\libpostproc.so
libs\armeabi\libswresample.so => app\src\main\jniLibs\armeabi\libswresample.so
libs\armeabi\libswscale.so => app\src\main\jniLibs\armeabi\libswscale.so
libs\armeabi\libtbb.so => app\src\main\jniLibs\armeabi\libtbb.so
libs\javacpp.jar => app\libs\javacpp.jar
libs\javacv.jar => app\libs\javacv.jar
res\ => app\src\main\res\
src\ => app\src\main\java\
Next Steps:
You can now build the project. The Gradle project needs network
connectivity to download dependencies.
Bugs:
If for some reason your project does not build, and you determine that
it is due to a bug or limitation of the Eclipse to Gradle importer,
please file a bug at http://b.android.com with category
Component-Tools.
(This import summary is for your information only, and can be deleted
after import once you are satisfied with the results.)
Build.Gradle:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig.with {
applicationId = "com.gst_sdk_tutorials.tutorial_4"
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 22
}
}
android.ndk {
moduleName = "tutorial-4"
cppFlags.addAll(["-I${file("src/main/jni/Common/native_app_glue")}".toString(),
"-I${file("src/main/jni/Common/cpufeatures")}".toString(),
"-I${file("src/main/jni/Common/ndk_helper")}".toString()])
ldLibs.addAll(["android", "EGL", "GLESv2", "dl", "log", "atomic"])
stl = "c++_static"
}
// jni is the default dir; config this if yours is in different directory
android.sources {
main {
jni {
source {
srcDirs 'src/main/jni'
}
}
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
// Turn on hard float support in armeabi-v7a
android.abis {
create("armeabi-v7a") {
cppFlags.addAll(["-mhard-float", "-D_NDK_MATH_NO_SOFTFP=1", "-mfloat-abi=hard"])
ldLibs.add("m_hard")
ldFlags.add("-Wl,--no-warn-mismatch")
}
}
android.productFlavors {
create ("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create ("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create ("x86-32") {
ndk.abiFilters.add("x86")
}
// for detailed abiFilter descriptions, refer to "Supported ABIs" #
// https://developer.android.com/ndk/guides/abis.html#sa
// build one including all productFlavors
create("fat")
}
}
dependencies {
compile 'com.android.support:support-v4:23.3.0'
compile files('libs/javacpp.jar')
compile files('libs/javacv.jar')
}
local.properties:
ndk.dir=C\:\\Users\\wiz\\Downloads\\android-ndk-r9d
sdk.dir=D\:\\sdk
.c file:(not complete due to character limit)
#include <string.h>
#include <jni.h>
#include <android/log.h>
#include <android/native_window.h>
#include <android/native_window_jni.h>
#include <gst/gst.h>
#include <gst/interfaces/xoverlay.h>
#include <gst/video/video.h>
#include <pthread.h>
GST_DEBUG_CATEGORY_STATIC (debug_category);
#define GST_CAT_DEFAULT debug_category
/*
* These macros provide a way to store the native pointer to CustomData, which might be 32 or 64 bits, into
* a jlong, which is always 64 bits, without warnings.
*/
#if GLIB_SIZEOF_VOID_P == 8
# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(*env)->GetLongField (env, thiz, fieldID)
# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)data)
#else
# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(jint)(*env)->GetLongField (env, thiz, fieldID)
# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)(jint)data)
#endif
/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably
* confuse some demuxers. */
#define SEEK_MIN_DELAY (500 * GST_MSECOND)
/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
jobject app; /* Application instance, used to call its methods. A global reference is kept. */
GstElement *pipeline; /* The running pipeline */
GMainContext *context; /* GLib context used to run the main loop */
GMainLoop *main_loop; /* GLib main loop */
gboolean initialized; /* To avoid informing the UI multiple times about the initialization */
ANativeWindow *native_window; /* The Android native window where video will be rendered */
GstState state; /* Current pipeline state */
GstState target_state; /* Desired pipeline state, to be set once buffering is complete */
gint64 duration; /* Cached clip duration */
gint64 desired_position; /* Position to seek to, once the pipeline is running */
GstClockTime last_seek_time; /* For seeking overflow prevention (throttling) */
gboolean is_live; /* Live streams do not use buffering */
} CustomData;
/* playbin2 flags */
typedef enum {
GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */
} GstPlayFlags;
/* These global variables cache values which are not changing during execution */
static pthread_t gst_app_thread;
static pthread_key_t current_jni_env;
static JavaVM *java_vm;
static jfieldID custom_data_field_id;
static jmethodID set_message_method_id;
static jmethodID set_current_position_method_id;
static jmethodID on_gstreamer_initialized_method_id;
static jmethodID on_media_size_changed_method_id;
/*
* Private methods
*/
/* Register this thread with the VM */
static JNIEnv *attach_current_thread (void) {
JNIEnv *env;
JavaVMAttachArgs args;
GST_DEBUG ("Attaching thread %p", g_thread_self ());
args.version = JNI_VERSION_1_4;
args.name = NULL;
args.group = NULL;
if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) {
GST_ERROR ("Failed to attach current thread");
return NULL;
}
return env;
}
/* Unregister this thread from the VM */
static void detach_current_thread (void *env) {
GST_DEBUG ("Detaching thread %p", g_thread_self ());
(*java_vm)->DetachCurrentThread (java_vm);
}
/* Retrieve the JNI environment for this thread */
static JNIEnv *get_jni_env (void) {
JNIEnv *env;
if ((env = pthread_getspecific (current_jni_env)) == NULL) {
env = attach_current_thread ();
pthread_setspecific (current_jni_env, env);
}
return env;
}
android.mk before import:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tutorial-4
LOCAL_SRC_FILES := tutorial-4.c
LOCAL_SHARED_LIBRARIES := gstreamer_android
LOCAL_LDLIBS := -llog -landroid
include $(BUILD_SHARED_LIBRARY)
ifndef GSTREAMER_SDK_ROOT
ifndef GSTREAMER_SDK_ROOT_ANDROID
$(error GSTREAMER_SDK_ROOT_ANDROID is not defined!)
endif
GSTREAMER_SDK_ROOT := $(GSTREAMER_SDK_ROOT_ANDROID)
endif
GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_SDK_ROOT)/share/gst-android/ndk-build/
include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS) $(GSTREAMER_PLUGINS_NET_RESTRICTED)
GSTREAMER_EXTRA_DEPS := gstreamer-interfaces-0.10 gstreamer-video-0.10
include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer.mk
I suggest to move to AS but keep the NDK build "the traditional way". My main argument to defend this approach is that the experimental plugin is still a "moving target": the DSL changes all the time, and its limitations require workarounds that change with every release of the experimental plugin. The second reason is that 3rd party tools like Fabric will not work with the experimental plugin.
For the non-experimental plugin, you can use the following piece in build.gradle:
def ndkBuild = android.ndkDirectory
import org.apache.tools.ant.taskdefs.condition.Os
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkBuild += '.cmd'
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
commandLine '$ndkBuild', 'NDK_PROJECT_PATH="$jniSrc/..'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
commandLine '$ndkBuild', 'clean', 'NDK_PROJECT_PATH="$jniSrc/..'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
tasks.all {
task -> if (task.name.contains('compileDebugNdk') || task.name.contains('compileReleaseNdk')) task.enabled = false
}

Categories

Resources