Showing posts with label Android Development. Show all posts
Showing posts with label Android Development. Show all posts

Friday, October 26, 2018

Build AI Camera App (Caffe2)

AI Camera app from Facebook is an example app that shows how to build Caffe2 on Android platform. Unfortunately, you will find that it does not work with the latest Android Studio. Here is how to get it to work.

One of the main reasons that it does not build is because starting with NDK r18b, GCC has been removed. The easiest way to get it working is to download older version, say r17c, and edit local.properties file and change ndk.dir to r17c folder.

Other than that, a couple of minor changes. In gradle.build file, update gradle version to 3.2.1 as below:

classpath 'com.android.tools.build:gradle:3.0.1'
classpath 'com.android.tools.build:gradle:3.2.1'


Lastly, edit gradle/wrapper/gradle-wrapper.properties file and change gradle tool version to 4.6 as below:

distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip


After all these changes, the app should successfully build! Happy hacking!

Build Caffe2 using Android NDK

Starting with Google's Android NDK r18b, gcc has been removed (history). That is, only one has to use clang as the toolchain. This may cause some problems if you do not set its toolchain as clang.

In fact, when you try to build Caffe2 for Android with android-ndk, it will fail, complaining

GCC is no longer supported.  See
  https://android.googlesource.com/platform/ndk/+/master/docs/ClangMigration.md.

The solution is to simply edit pytorch/scripts/build_android.sh file, replacing gcc to clang for ANDROID_TOOLCHAIN variable, as shown below:

CMAKE_ARGS+=("-DANDROID_TOOLCHAIN=gcc")
CMAKE_ARGS+=("-DANDROID_TOOLCHAIN=clang")

Happy hacking!

Tuesday, April 17, 2018

Android Camera2 Bare Minimum Code Sample

Google has replaced camera API with camera2 API a few years ago. I guess it is a good thing that Google is working hard to improve Android, personally I think camera2 API is just so difficult. Compared to the deprecated camera API, it requires so much more code.

I am trying to understand this new camera2 API, and it is just not easy. I looked at Google's Camera2Basic sample code, it is still daunting for Android beginners like myself. Well, here is my attempt to trim down this fat sample code into the bare minimum so that it is easier to understand the fundamentals of the camera2 API.

All it does is to connect to a camera and display its preview to the screen. No capture, no manual focus, no error checks, etc. I am not happy that even this bare-bone app requires so many lines. Anyways, I will add more functionalities in the upcoming post.



Saturday, March 17, 2018

Solution to Android CountDownTimer Skipping the Last Tick

Google's implementation of CountDownTimer in Android is a bit strange; it often skips the very last tick. I can see why they did it this way: they want to make sure that onFinish() function will be called with no delay in the case onTick() takes so much time. However, this implantation causes the last tick to skip pretty much.

Well, here is my modified version of CountDownTimer which will not skip the last tick, unless onTick() function takes too long, which it shouldn't. So, make sure that onTick() will return quickly first.

The code modification starts at line 114 below:
The original source code is taken from here.

Saturday, February 11, 2017

Android Threading: Handler Example

In this post, we will go over a very simple Handler example for Android development. Hopefully this post will explain and demonstrate why and how to use Handler class in Android.

Consider a very simple app, where you have two buttons: task button and increment button.

Upon click, the task button will notify the user that the task is now running, and carry out some heavy task, which may take up to seconds. When complete, it will notify the user that the task is finally done.

Upon click, the increment button will simply increment counter and display its current value.

Let's take a look at a crude attempt to implement this using a simple Thread. Here is the layout file.

Here is the implementation activity file.


Here, upon the task button click, it launches the task, which is simulated by sleep(3000), on a separate thread so that we don't slow down the main UI thread. However, the problem is that we must wait for this task thread to complete because we need to update the button's text upon completion. Thus, we use join() method to wait for the task to complete. With this implementation, we find that the UI thread becomes unresponsive while waiting. This is NOT a good way of implementing the task.

The core problem is that we ask the task thread to carry out some heavy task, and we need to make sure that the main UI thread does not just sit and wait, but rather do its jobs on its own. The task thread then must communicate with the UI thread and let it know the task is complete, at which point, the UI thread can update the UI accordingly.

The Handler class in Android achieves exactly this, and below is modification that makes use of the Hander class.


As you can see, the task thread will do its job, and when the task is complete, it notifies the main UI thread that the job is done through handler. The handler is created in the main activity, so it is bound to the main UI thread. When the handler receives a message from the task thread that the job is complete, it will then update the button's text. In the meantime, the main UI task carries out its own tasks, such as incrementing the counter when the increment button is pressed.

Of course, one can implement this without using the Handler class, shown below. However, this solution is possible because we are communicating with the UI thread in this example. If, however, you have two different task threads that must communicate with each other, then you need to use the Handler.

Tuesday, February 7, 2017

How to Load Java OpenCV Library to Android Studio

In this tutorial, I will go through a step by step method to load Java OpenCV Library to Android Studio.

First, download OpenCV for Android from here. Extract the zip file, and you should see OpenCV-android-sdk folder.

Next, in Android Studio, open up a project where you want to integrate OpenCV Java library. Then, click File - New - Import Module and select OpenCV-android-sdk/sdk/java folder. Android Studio will ask about import option, and just accept the default.

You should see OpenCVLibrary module in your Android project. Select its build.gradle file and set appropriate versions for compileSdkVersion, buildToolsVersion, etc.

Now, you need to add dependency. Open up your app's build.gradle file and add
compile project(':openCVLibrary310')
into dependencies { ... } section.

Next, you will need to make sure that your app loads in the OpenCV library. Go to the activity class file that first uses OpenCV Library, and add static statement, similar to below:

...
import org.opencv.android.OpenCVLoader;

public class MainActivity extends Activity {
    final static String TAG = "Main Activity";

    static {
        if(!OpenCVLoader.initDebug()){
            Log.d(TAG, "OpenCV not loaded");
        } else {
            Log.d(TAG, "OpenCV loaded");
        }
    }
...

Finally, you will need to copy native binary files. Copy OpenCV-android-sdk/sdk/native/libs folder as src/main/jniLibs folder in your app's directory.

That's it! You should now be able to use OpenCV functions in your app!

Monday, November 7, 2016

OpenCV for Android Integration with NDK in Studio 2.2+

Starting with Android Studio 2.2+, NDK integration has become much easier. Thanks a lot, Google!

In the previous post, I showed you how to import OpenCV Android Tutorial 2 sample app into Android Studio and build with NDK integration, which admittedly was quite complicated. I am happy to present much easier method here in terms of NDK integration, starting from Android Studio 2.2.

The only difference from the past post lies in the App module's build.gradle file. The new file should resemble this:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "24.0.3"

    defaultConfig {
        applicationId "org.opencv.samples.tutorial2"
        minSdkVersion 8
        targetSdkVersion 22

        ndk {
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }

}

dependencies {
    compile project(':openCVLibrary310')
}

That's it! This will now let Android Studio successfully load C/C++ source files in the src/main/jni directory with valid syntax correction, etc.

Sunday, October 23, 2016

How to Mark C/C++ Files in Android Studio

UPDATED: please refer to this post for much simpler way! The instruction below is officially deprecated.

There are basically two ways to link native C/C++ files in Android Studio. One way is to use CMake, and the other is to use NDK-BUILD tool. In OpenCV Android samples, it does it by NDK-BUILD tool. as you can see here. However, the problem with NDK-BUILD method is that Android Studio does not treat JNI native source files as C/C++ files; it is quite annoying to code directly in Android Studio when you don't have function-completion features or auto-syntax checks, etc.

Here, I will show you how to trick Android Studio to mark JNI native source files as C/C++ files when building with NDK-BUILD method. Basically, I will add CMake file to link C/C++ file folder for compilation so that Android Studio will mark all C/C++ files in the folder as C/C++ with correct syntax guide. For more info on adding C/C++ support in Android Studio, refer to Google's official documentation.

First, Install NDK and CMake components for your Android Studio. Also make sure that you are running Android Studio 2.2 or higher.

Locate C/C++ files that are linked with your Android project. This is probably src/main/jni folder in the app module directory. Create an empty C/C++ file in the folder: src/main/jni/empty.cpp.

Next, create CMakeLists.txt file in the app's directory with the following content:
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib
             SHARED
             src/main/jni/empty.cpp )
include_directories(/usr/include/)
include_directories(/usr/local/include/)

The last parameter should point to the newly created empty C/C++ file. Also make sure to add as many include directories as needed. 

Next, add the following lines in the app module's build.gradle file:
android {
...
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
...
}

Now, sync gradle file and compile. You will notice that Android Studio now considers all C/C++ files in the src/main/jni folder as native C/C++ files. You can now directly edit your C/C++ files from Android Studio with syntax checks, method completion, etc!


Saturday, October 22, 2016

How to Restore Nexus Devices to Factory Images

I have Nexus 4 device which I do not use anymore. I decided use it for Android development. Here is how to flash/restore Nexus device to factory image. This post is basically a short-form recap of Google's official document.

Step 1, download the appropriate factory image at the right side of this webpage.

Step 2, unzip it and locate flash-all.sh file.

Step 3, restart your Android phone into fastboot mode. You can connect your Nexus and run the following command from a computer:
$ adb reboot bootloader
or use key-combos found here.

Step 4, while Nexus is connected to the computer and booted up in fastboot mode, execute flash-all.sh file from your computer as root. You need fastboot utility. If you have Android Studio installed, you already have it. Otherwise, you could download the command line SDK from here. Make sure to run with root privilege!
$ sudo ./flash-all.sh

That's it! It will automatically carry out some tasks and reboots, and restore your phone into factory image.

Saturday, October 15, 2016

Android Studio .GITIGNORE File

This is my personal Android Studio .gitignore file:
.gradle
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
*.apk
*.ap_
*.dex
*.class
bin/
gen/
Thumbs.db
.DS_Store
.classpath
.project
*.iml
.idea
.gradle
build/
obj/
/*/out
/*/*/build
/*/*/production
*.iws
*.ipr
*~
*.swp
*.so
*.a

How to Integrate OpenCV for Android Tutorial 2 and Tutorial 3 Modules

OpenCV Android Tutorial 2 shows how to setup JNI to import C++ native code, while Tutorial 3 shows how to control Android camera to take a picture. In this tutorial, I will go over step by step how to integrate Tutorial 2 and Tutorial 3 modules; that is, we will be building an app that will both let us import native C++ OpenCV code and control Android camera to take picture.

To me, it seems easier to integrate JNI into Tutorial 3 module, so the following will simply add JNI capability to Tutorial 3 module.

First, import Tutorial 3 module from OpenCV Android.

Next, edit openCVTutorial3CameraControl/build.gradle file to use NDK, similar to below:
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "24.0.3"

    defaultConfig {
        applicationId "org.opencv.samples.tutorial3"
        minSdkVersion 8
        targetSdkVersion 22

        ndk {
            moduleName "camera_control" // this is the native module name
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs = []
    }

    task ndkBuild(type: Exec) {
        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
        } else {
            commandLine '/home/linuxnme/Android/Sdk/ndk-bundle/build/ndk-build', '-C', file('src/main').absolutePath // replace with your path
        }
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }
}

dependencies {
    compile project(':openCVLibrary310')
}

Make sure to note NDK module name; in my case it is set to camera_control. Also, make sure to compile openCVLibrary with the same SdkVersion by editing the library's build.gradle file.

Next, edit Tutorial3Activity.java file to look like following:
...
public class Tutorial3Activity extends Activity implements CvCameraViewListener2, OnTouchListener {
    private static final String TAG = "OCVSample::Activity";
...
    public native void FindFeatures(long matAddrGr, long matAddrRgba);
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    System.loadLibrary("camera_control");
                    mOpenCvCameraView.enableView();
                    mOpenCvCameraView.setOnTouchListener(Tutorial3Activity.this);
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
...

   public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        Mat mRgba =  inputFrame.rgba();
        Mat mGray = inputFrame.gray();
        FindFeatures(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
        return mRgba;
    }
...

Make sure to use the same native module name.

Next, copy jni folder from Tutorial 2. Edit Application.mk file to set
APP_ABI := all

Edit Android.mk file to change JNI module name:
LOCAL_MODULE    := camera_control

Also, edit line 12 of this file to correctly point to your jni folder of OpenCV Android SDK.

Edit jni_part.cpp to correct the function names as below:
...
extern "C" {
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Tutorial3Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba);

JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial3_Tutorial3Activity_FindFeatures(JNIEnv*, jobject, jlong addrGray, jlong addrRgba)
{
    Mat& mGr  = *(Mat*)addrGray;
    Mat& mRgb = *(Mat*)addrRgba;
    vector<KeyPoint> v;
...

Enjoy Android development!

Android Studio - How to View Method Parameters

On Linux, press <Ctrl> + P
On Mac, press <Command> + P

Wednesday, October 12, 2016

Installation of Multiple Instances of the Same Android App

Sometimes, you have your template app, from which you develop different apps. However, Android will count apps that have branched from the same app as one app.

Say you have your template app T. You modify T and create app A. You also create app B by modifying another copy of T. Now, you want to install both apps A and B into your phone, but it won't work; one will overwrite the other, because A, B have branched from T.

One way to install both A and B on a single phone is to change their applicationid in the app's build.gradle file. In most case, the applicationid is identical to the main activity package name. Make sure to change the top-most name of applicationid. After the change, build clean and invalidate caches and restart Android Studio. 

Now, you should be able to install both A and B as long as their applicationid's are different.

Tuesday, July 26, 2016

How to Compile ZXING Barcode Scanner App in Android Studio Part 2

This is a follow-up from the previous post. Here, I will cover how to compile only from source files, without using pre-built jar files.

We will resume from where we left off from the previous post. Select File -> Project Structure and click on + icon. Select Java Library and set the library name as core and edit the package to be com.google.zxing. Leave class name as MyClass, as we will delete this file in a moment.

When the module has been created, you will see core directory in the project's root directory. Copy all files and folders from zxing source directory, i.e., zxing/core/src/main/java/com/google/zxing/ to the project's core/src/main/java/com/google/zxing/ directory. Delete MyClass.java file, which has been automatically created by Android Studio when creating this module.

Next, you will need to add module dependency. Add the following lines to app module's build.gradle file:
...
dependencies {
    compile project(':core')
}

Lastly, you will also need to add zxing/android-core module into this project. Since this consists of only a single file, it is easiest to simply copy this file into the app module. Copy zxing/android-core/src/main/java/com/google/zxing/client/android/camera/CameraConfigurationUtils.java file from the zxing source directory into the project's app/src/main/java/com/google/zxing/client/android/camera/ directory. Note that this is the app module's directory, not core library's directory.

Now, you should be able to compile the project!


NOTE: Depending on your configuration, you may receive an error similar to:
Error:Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been compiled using Java 8 or above.
If you are using the 'java' gradle plugin in a library submodule add 
targetCompatibility = '1.7'
sourceCompatibility = '1.7'
to that submodule's build.gradle file.

To resolve this, simply do what it asks. That is, copy the above two lines of codes into core module's build.gradle file, which should look similar to:
apply plugin: 'java'

targetCompatibility = '1.7'
sourceCompatibility = '1.7'

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Monday, July 25, 2016

How to Compile ZXING Barcode Scanner App in Android Studio Part 1

In this post, I will cover how to compile stand-alone zxing's Barcode Scanner app in Android Studio.

First, download the zxing's latest source files from here or run git clone:
$ git clone https://github.com/zxing/zxing

Next, launch Android Studio and choose Import project (Eclipse ADT, Gradle, etc) and choose zxing/android folder. Select all three check boxes when prompted, and finish importing.

In the app module's build.gradle file, edit compileSdkVersion, buildToolsVersion, minSdkVersion, and targetSdkVersion values if necessary.

Try to compile the project. It will complain with the following error:
Error:(19, 24) error: cannot find symbol class Result

That is, in the HistoryItem.java file, importing com.google.zxing.Result cannot be resolved. This is because we need to link zxing/core library. You could either import zxing/core source files and compile, or simply include pre-built jar file.

In this post, I will go through the method of linking pre-built jar file. If you are curious as to how to compile the project all from source files, go straight to my follow up post.

To compile using pre-built jar files, go to zxing's maven release repository and navigate to zxing/core/ and download the latest version of jar file. I downloaded core-3.2.1.jar file.

Next, create app/src/main/libs directory in the project and copy core-3.2.1.jar file here. Now we need to include this file as a library in Android Studio. You could do this by right-clicking this jar file in Android Studio Project pane and selecting Add to Library,which will add the following lines of code in app's build.gradle file:
dependencies {
    compile files('src/main/libs/core-3.2.1.jar')
}

You can try to compile the project again, but it will probably prompt another error:
Error:(124, 24) error: cannot find symbol variable CameraConfigurationUtils

Again, this is because we need zxing/android-core library in order to compile the app. Similar to zxing/core library, we go to the zxing's release repository and navigate to zxing/android-core/ and download the latest version of jar file. I downloaded android-core-3.2.1.jar file.

Similar to the core library file, we need to copy this file into app/src/main/libs directory in the project and select Add to Library. Your app's build.gradle should read:
...
dependencies {
    compile files('src/main/libs/core-3.2.1.jar')
    compile files('src/main/libs/android-core-3.2.1.jar')
}

Now, you should be able to compile the app!

Saturday, July 23, 2016

How to Compile Mixed Processing OpenCV Tutorial App on Android Studio

The second OpenCV for Android tutorial app, namely Mixed Processing, differs from Camera Preview app in that it also has a C++ source file, thus requiring Android NDK. To compile this project in Android Studio, the first several steps are identical to Camera Preview app, so follow instructions in my previous post. In summary, these steps that are required to integrate OpenCV for Android SDK statically are:

1. Download OpenCV for Android and unzip
2. Import the tutorial project to Android Studio
3. Adjust the Android API and SDK Tools version in the app and library module build.gradle files
4. Copy OpenCV Android native library folder into the app module folder and rename it as jniLibs
5. Add OpenCV static initializing code to the main activity java file
6. Add appcompat dependency in the app module build.gradle file (for API 23 or above only)
7. Add camera permission code in the java file (for API 23 or above only)
8. Change the theme in AndroidManifest.xml file (for API 23 or above only)

Even after all the above changes, the project will still not compile because it contains native C++ file, which we must let Android Studio know what to do with. So, here we go again! I will assume the project directory of ~/AndroidStudioProjects/tutorial-2-mixedprocessing. Before we do anything further, make sure to install Android NDK from SDK Manager.

When you try to compile the project, it will complain with the following error message:
Error:(12, 0) NDK integration is deprecated in the current plugin.
Consider trying the new experimental plugin
Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration

Let's do what it asks for. You probably do not have this gradle.properties file yet, so let's create it.
$ echo "android.useDeprecatedNdk=true" > ~/AndroidStudioProjects/tutorial-2-mixedprocessing/gradle.properties

When you try to build the project, it will now complain with two errors:
Error:(2, 33) opencv2/core/core.hpp: No such file or directory
...
Error:Execution failed for task ':openCVTutorial2MixedProcessing:compileDebugNdk'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '~/Library/Android/Sdk/ndk-bundle/ndk-build'' finished with non-zero exit value 2

Let's tackle these errors one by one. Open up the app module's build.gradle file, and edit it similar to below:
import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "org.opencv.samples.tutorial2"
        minSdkVersion 8
        targetSdkVersion 23

        ndk {
            moduleName "mixed_sample"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }

    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
        jni.srcDirs = []
    }

    task ndkBuild(type: Exec) {
        if (Os.isFamily(Os.FAMILY_WINDOWS)) {
            commandLine 'ndk-build.cmd', '-C', file('src/main').absolutePath
        } else {
            commandLine '~/Library/Android/Sdk/ndk-bundle/ndk-build', '-C', file('src/main').absolutePath // replace with your path
        }
    }

    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }
}

dependencies {
    compile project(':openCVLibrary310')
    compile 'com.android.support:appcompat-v7:23.0.0'
}

Note that you must replace ~/Library/Android/Sdk/ndk-bundle/ndk-build with the NDK path in your system. You can check this in local.settings file, which will have a line similar to
ndk.dir=~/Library/Android/Sdk/ndk-bundle
You can simply use this path followed by /ndk-build, as shown above.

Now try to build the project again, and you will see the first error message is gone. To solve the last error, edit the app module's jni/Android.mk file as shown below:
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
include ~/Downloads/opencv3.1/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk // Replace this with  your own path where you have extracted OpenCV for Android

LOCAL_MODULE    := mixed_sample
LOCAL_SRC_FILES := jni_part.cpp
LOCAL_LDLIBS +=  -llog -ldl

include $(BUILD_SHARED_LIBRARY)

Again, make sure to replace ~/Downloads/opencv3.1/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk with the appropriate path.

Finally, if you plan to run the app on x86 emulator or devices, you must also edit app module's jni/Application.mk file and replace APP_ABI := armeabi-v7a with APP_ABI := all.

 At last, you should be able to compile and run this Mixed Processing tutorial app on your device or emulator!

By the way, if you think you are missing the menu (Such as Samsung Galaxy phones), press-and-hold the back button; it will show the menu items in the full-screen mode.

How to Compile CameraPreview OpenCV Tutorial App on Android Studio

First, download the latest OpenCV for Android from here. At the time of writing this post, the latest version is OpenCV 3.1.0. I will assume that you have downloaded the file in ~/Downloads folder.

Unzip the contents by running
$ unzip OpenCV-3.1.0-android-sdk.zip

Next, open up Android Studio, and select Import project (Eclipse ADT, Gradle, etc.) and choose ~/Downloads/OpenCV-android-sdk/samples/tutorial-1-camerapreview

Choose the import destination directory as desired. I will assume it to be ~/AndroidStudioProjects/tutorial-1-camerapreview

Check all three boxes and click on finish.

Now, you should be prompted with an auto-generated Eclipse Android Project Import Summary. In the messages box below, you may probably see
Error:Cause: failed to find target with hash string 'android-14' in: /data/Android/Sdk
Install missing platform(s) and sync project

To fix this, open up build.gradle files for both the openCVLibrary module and openCVTutorial module. Make sure to change compile and target SDK versions appropriately. I will use API 23 and Build Tools 23.0.3 throughout this post, but your versions may differ from me. For example, gradle.build file for the openCVLibrary should read

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 23
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

and openCVTutorial module's build.gradle should read

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "org.opencv.samples.tutorial1"
        minSdkVersion 8
        targetSdkVersion 23
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile project(':openCVLibrary310')
}

Now, you should be able to successfully compile the project. Try running the app on your device or emulator. You will probably be encountered with Package Not Found message, unless you already have OpenCV Manager installed on your device. You should be able to successfully run the app after installing OpenCV Manager!

In case you do not want to require OpenCV Manager on the device, it is possible to link the OpenCV library as a static library. To do this, you will first need to copy the native library folder to the project directory and name it as jniLibs:
$ cp -r ~/Downloads/OpenCV-android-sdk/sdk/native/libs ~/AndroidStudioProjects/tutorial-1-camerapreview/openCVTutorial1CameraPreview/src/main/jniLibs

Next, you will need to insert static initialization code into the main activity java file at ~/AndroidStudioProjects/tutorial-1-camerapreview/openCVTutorial1CameraPreview/src/main/java/org/opencv/samples/tutorial1/Tutorial1Activity.java:

...
public class Tutorial1Activity extends Activity implements CvCameraViewListener2 {
    static {
        if (!OpenCVLoader.initDebug()) {
            Log.v("OpenCV", "ERROR: OpenCV Library Load Failed");
        } else {
            Log.v("OpenCV", "OpenCV Library Load Successful");
        }
    }
...

where 7 lines starting from static have been inserted.

You should now be able to compile and run the app without OpenCV Manager app on the device. Sometimes, you need to clean build and rebuild the project, or select File -> Invalidate Caches / Restart option to get it take effect. If it still says it requires OpenCV Manager, make sure to delete the original app from the device, rebuild the app, and re-run the app.

NOTE - if you are compiling for Android API 23 or above, you will need to set permission for the camera. Follow the instructions below:

1. Add a dependency in openCVTutorial module's build.gradle file to read
...
dependencies {
    compile project(':openCVLibrary310')
    compile 'com.android.support:appcompat-v7:23.0.0'
}
...

Make sure to insert the appropriate repository version in place of v7:23.0.0; Else, you could always install one.

2. Let the main activity extend AppCompatActivity and add permission request code in the main java file:
...
import android.Manifest;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
...
public class Tutorial1Activity extends AppCompatActivity implements CvCameraViewListener2 {
...
    public void onCreate(Bundle savedInstanceState) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.CAMERA},
                0);
...

This is the bare minimum code to access camera for API 23 and above. For more details and practical coding, please refer to Android's official document.

3. In openCVTutorial module's AndroidManifest.xml file, replace android:theme="@android:style/Theme.NoTitleBar.Fullscreen" with android:theme="@style/Theme.AppCompat.Light".

Now, you should be able to run the app without OpenCV Manager installed! If you are running on the emulator, make sure to go to the advanced option to emulate back camera.

Sunday, June 26, 2016

Android Development - Access Activity Instances from Other Classes

Each page on Android app is defined by an activity instance or an object. Sometimes, you may want to edit the instance externally, i.e., from other objects or classes. The following code shows how to do access the instance of MainActivity class externally:

...
public class MainActivity extends Activity {
  private static MainActivity instance;
  private static void setInstance (MainActivity instance) {
    MainActivity.instance = instance;
  }
  public static MainActivity getInstance () {
    return instance;
  }
  public void somePublicMethod () {
  ...
  }
  public void onCreate (Bundle savedInstanceState) {
    super.onCreate (savedInstanceState);
    setContentView (R.layout.activity_main);
    setInstance (this);
    ...
  }
  ...
}

As you can see from the code above, static variable instance is to be assigned in the onCreate method. Now, this instance can be accessed externally by calling the public getInstance method, as shown below:

...
public class SomeClass {
  public void someMethod () {
    MainActivity.getInstance().somePublicMethod();
  }
}

This method is called singleton design, as there is only one instance of the Activity class, which we want to access externally.