Showing posts with label JNI. Show all posts
Showing posts with label JNI. Show all posts

December 30, 2011

Android NDK JNI Windows xp/7 with 32/64 bit Installation Problems with Solutions in Eclipse without C/C++ CDT Plugin

Hi all,

I spent 2 days on configuring this. I read lot of blogs and instrutction steps from various sites. I would like share my experience on installing Android NDK and Working with Eclipse.

Objective:
Using JNI Technology in Eclipse with Android NDK r6/r7 on Windows xp/7 Professional

Pre-requirements:
  1. Java SE SDK -- Java Development Kit
  2. Eclipse Helios/Indigo -- IDE to work with Java, Android, C/C++ etc.
  3. Android SDK -- Android Applications Development Kit
  4. Android ADT Plugin for Eclipse -- Download the latest Android SDK Platform Tools
  5. C/C++ Plugin for Eclipse (Optional) -- Make sure that .c, .cpp, .h files opening from Eclipse
  6. Android NDK (r6/r7) -- Native development i.e. Running c libraries in Android
  7. Cygwin 1.7.x or above -- Makefile creation, Library file creation tools, Compiling C files

Installation:
  1. Install the Java Development Kit
  2. Install the Android SDK and ADT Plugin with Eclipse
  3. [Optional] Install CDT plugin for Eclipse
  4. Download and extract the Android NDK
  5. Install Cygwin 1.7.x or above
Note: Don't extract in a folder where folder name is having spaces in between words.
Example:
"Program Files" -- Don't Use
"ProgramFiles" -- Use

Configuration:
Please make sure that you have set the environment variables like
  • JAVA_HOME -- Java Home Directory
  • NDK_HOME -- Android NDK Home Directory
  • Update Path Variable with JDK Bin folder
Creating Android Application
  • In Eclipse, Select File->New->Android Project
  • Enter the Project Name and Click on "Next" button
  • Select the "Build Target", I opted for Android 2.2, SDK 8 Version and Click on "Next" button
  • In Application Info dialog, enter the "Package Name" and Select "Finish" button
  • Now, you can see the newly created SampleNDK project in the eclipse project explorer window

Example:
  • Eclipse Workspace Folder: D:\Workspace
  • Android Application Name: SampleNDK
  • Android Application Working Folder: D:\Workspace\SampleNDK
  • Package Name: com.samplendk
  • Android Application Source Folder: D:\Workspace\SampleNDK\src

Source of AndroidNDKActivity.java
package com.samplendk;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;

public class SampleNDKActivity extends Activity {
   
    //Declare the native method
    private native String invokeNativeFunction();
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        //Call the native methods
        String hello = invokeNativeFunction();
        new AlertDialog.Builder(this).setMessage(hello).show();
    }
   
}

  • Create a folder named "jni" in the project
    • Right click on the "SampleNDK" project-> Select "New"-> Select "Folder"->Type "jni"
  • Create files "Android.mk" and "native.c" in Jni folder
    • Right click on the "jni" folder-> Select "New"-> Select "File"->Type "Android.mk"
    • Right click on the "jni" folder-> Select "New"-> Select "File"->Type "native.c"
  • After Creating those folder and files, the project explorer window look like this
  • Do some continuous steps.
    • Build, Refresh, and Clean project
      • Right Click on the "SampleNDK" project and Select the "Build Project"
      • Select "Sample NDK" project and Click "F5" button on keyboard
      • Select "Project" menu and Select "Clean" option

  • Create header file of the java file
    • In windows command prompt, change to project source directory
    • Syntax:
      • cmd>
      • cmd> cd ProjectDir/src

    • Example:
      • cmd> D:
      • D:\> cd SampleNDK/src
    • Run the Javah command to create header file
    • Syntax:
      • cmd> javah -jni .javafile_without_.java_extension // JDK 1.7
      • cmd> javah -classpath ..\bin\classes .javafile_without_.java_extension //JDK1.6
    • Example:
      • D:\SampleNDK\src> javah -jni com.samplendk.SampleNDKActivity //JDK1.7
      • D:\SampleNDK\src> javah -classpath ..\bin\classes com.samplendk.SampleNDKActivity //JDK1.6
    • Note:
      • Don't include the .java at the end of javah command

  • Copy the created java header file to jni folder
    • D:\SampleNDK\src> copy com_samplendk_SampleNDKActivity.h ..\jni

  • Go to Eclipse and Refresh the project by pressing "F5" on keyboard.
  • Open the header file from jni folder
  • Copy the function created by javah as shown below
  • Paste the code in native.c and change the code similar to this
Source of native.c
#include <string.h>
#include "com_samplendk_SampleNDKActivity.h"

jstring JNICALL Java_com_samplendk_SampleNDKActivity_invokeNativeFunction
  (JNIEnv *env, jobject obj)
{
    return (*env)->NewStringUTF(env, "Hello from native function !!");
}

Source of Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := SampleNDK
LOCAL_SRC_FILES := native.c

include $(BUILD_SHARED_LIBRARY)

  • Run Cygwin.bat file in the Cygwin installed directory
  • It will open the cygwin command prompt
  • Change the directory to SampleNDK project directory
    • Note: All the drives in your systems are mounted to some directory in the cygwin.
    • To see your drive mount points type mount
    • # mount
  • # cd /cygdrive/d/SampleNDK/
  • Run the ndk-build command from the android ndk directory
    • # /cygdrive/d/android-ndk-r7/ndk-build

  • Error(Only in Android-ndk-r7):
  • You may get some error like the following
    • /awk.exe: can't open file check-awk.awk
    • Andoid NDK: Host 'awk' tool is outdated. Please define
    • HOST-Awk to Point to Gawk or Nawk !
  • Resolution:
    • Goto the android-ndk/prebuilt/windows/bin/
    • Change the awk.exe to awk_.exe

  • Now you may see the following output after successful execution
  • After successful creating libSampleNDK.so file, refresh your Eclipse project
  • You can see the updated "Project Explorer" with "libs" folder in the tree hierarchy
  • Update the java source code now by adding this library to it
Source code of SampleNDKActivity.java
package com.samplendk;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;

public class SampleNDKActivity extends Activity {
   
    static
    {
        System.loadLibrary("SampleNDK");
    }

   
    //Declare the native method
    private native String invokeNativeFunction();
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        //Call the native methods
        String hello = invokeNativeFunction();
        new AlertDialog.Builder(this).setMessage(hello).show();
    }
   
}

  • Clean the project by Selecting "Project"->"Clean"
  • Run the application as "Android Application"
  • Note:
    • Error:
      • java.lang.unsatisfiedLinkError Library -- not found
    • Resolution:
      • Please see if you have added the "lib" in java source before adding the library in System.loadLibrary() method
  • Please find the screenshot of above running program in emulator


If you have queries, please mail to psrdotcom@gmail.com

December 27, 2011

Java Native Interface (JNI) in Netbeans with C/C++ and Java Hello World Sample Source Code

Hi all,

Today I configured the Netbeans IDE to work with Java Native Interface (JNI).

Pre-Requisites:
  1. Java Development Kit (JDK)
  2. Cygwin (or) MinGW & MSYS
  3. NetBeans IDE with Java and C/C++ Bundle

Installation:
  • Install JDK
  • Install Cygwin (or) MinGW&MSYS
  • Note: While installing please choose the destination directory name without spaces
  • I have installed NetBeans IDE All Version, because I thought, I will need all the technologies. That is different approach.

Configuration:
  • Set the environment variables like JAVA_HOME and PATH with Java Installation Directory and JDK bin, Cygwin/MinGW&MSYS bin directories respectively
  • Cygwin/MinGW integration with NetBeans
  • Configure the C/C++ with Tools MinGW bin directory, which automatically fills the corresponding compilers

Source Code:

  • Create a sample java application with the following detail

package javaapp1.JavaApp1;

public class JavaApp1
{
public static void main(String [] args)
{
  new JavaApp1.nativePrint();
}

private native void nativePrint();
}

  • Clean and Build the java project
  • In Command Prompt, Navigate to Netbeans Project Directory
    • cmd> cd Netbeans/ProjectDir
  • Create the Java header file
    • cmd> javah -o JavaApp1.h -classpath JavaApp1\build\classes javaapp1.JavaApp1

  • Create a C/C++ Dynamic Library Project in Netbeans (In this example, it is CppDll1)
  • Change some of the project properties
  • Make sure that, you have downloaded and configured the proper Cygwin/MinGW with exact Architecture 32bit/64bit
  •  Make sure that you are using proper gcc for 32bit/64bit dll creation
  • Linker must be of same architecture, 32bit/64bit


  • Include the Java header file, which we have created in Java Project.
    • Right click on the "Source Files"-> Select "Add an Existing Item"
    • Select the created header file from Project Home Directory
    • (OR)
    • Manually copy the created header file from Project home directory to CppDll directory
  • Create a C Source file in "Source Files" in CppDll1 project
 #include "JavaApp1.h"

JNIEXPORT void JNICALL Java_javaapp1_JavaApp1_nativePrint(JNIEnv *env, jobject obj)
{
    printf("\nHello World from C\n");  
}
  • Clean and Build the C code. I have faced the following issue.
    • Issues Faced:
      • I am using Windows 7 64-bit and installed Jdk 64-bit. But initially I have installed MinGW 32 bit and it is generating only 32 bit DLL which is not suitable to run the Java application in NetBeans.
    • Resolution:
      • Downloaded MinGW 64 bit and configured in the NetBeans C/C++ Options
  • Copy the .dll file path
  • In Java project, open the main class and add the following content
package javaapp1.JavaApp1;

public class JavaApp1
{
static
{
  System.load("dll file path");
}
public static void main(String [] args)
{
  new JavaApp1.nativePrint();
}

private native void nativePrint();
}
  • Clean and Build the project
  • Run the Java project to see the final JNI output.

References:
http://java.sun.com/docs/books/jni/html/jniTOC.html
http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html
http://www.cygwin.com/
http://sourceforge.net/projects/mingw-w64/
http://netbeans.org/community/releases/71/install.html

Please send your feedback to psrdotcom@gmail.com

Featured Post

Java Introdcution

Please send your review and feedback to psrdotcom@gmail.com