ラベル Android の投稿を表示しています。 すべての投稿を表示
ラベル Android の投稿を表示しています。 すべての投稿を表示

2011年6月28日火曜日

Androidの他アプリからSkypeを起動する方法

From Evernote:

Androidの他アプリからSkypeを起動する方法

PackageManager packageManager = getPackageManager();

Intent skype = packageManager.getLaunchIntentForPackage("com.skype.raider");

// skype.setData(Uri.parse("tel:0123456789")); // これは効かなかった。方法ないのかな?

startActivity(skype);

 

2011年6月27日月曜日

AndroidのWebViewでLocalStorageを使う為の設定

From Evernote:

AndroidのWebViewでLocalStorageを使う為の設定

String databasePath = this.getApplicationContext().getDir("localstorage", Context.MODE_PRIVATE).getPath();
Log.d(LOG_TAG, "databasePath=" + databasePath);
webView = (WebView) findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabasePath(databasePath);
// webView.setWebChromeClient(new BabukumaWebClient());
webView.loadUrl(URL_TOP);
 

2011年4月14日木曜日

iPhoneとAndroidのURL Scheme起動設定方法

From Evernote:

iPhoneとAndroidのURL Scheme起動設定方法

iPhoneとAndroidのURL Scheme起動設定方法
ブラウザのリンクからアプリを起動する方法。
(及び他アプリからURL Schemeで起動する事も可能)


iPhone


<a href="babukuma:">アプリ起動</a>
のリンクで起動できる。パラメータを渡すのも可能。

<a href="babukuma:?a=1&b=2">アプリ起動</a>
<a href="babukuma://com.babukuma.demo.urlscheme/?a=1&b=2">アプリ起動</a>

起動時のデリゲート
iOS4.1までは
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
このデリゲートが呼ばれたが、
iOS4.2からは次のデリゲートが追加された。
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

両方実装すると
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
このデリゲートが優先される。

簡単な例は。。。
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    NSLog(@"url=%@, sourceApplication=%@", [url absoluteString], sourceApplication); 
    returnYES;
}



Android

AndroidManifest.xml


<a href="abukuma://com.babukuma.demo.urlscheme">アプリ起動</a>
リンクで起動できる。パラメータを渡すのも可能。


<a href="babukuma://com.babukuma.demo.urlscheme/?a=1&b=2">アプリ起動</a>

パラメータ以外もPath、Port指定も可能。




ブラウザからアプリを起動する為のHTMLサンプル

ブラウザからアプリを起動するのは簡単にできるか、
ユーザがアプリを先にインストールしないブラウザでエラーページが表示されてしまう。
アプリがインストールされている場合はアプリを起動し、
インストールされてない場合はダウンロード先へ移動させたい。

参照したサイトのURLは忘れたけど、どこか外国のiPhone開発QAサイトでヒントを見つけて一応解決。



2011年2月27日日曜日

Mac OS X + Android + OpenCV2.2

参照:Android - OpenCV Wiki
Ubuntu 10.10 + Android + OpenCVの環境をセットアップ(hironemu's blog)

この前「hironemu」さんのブログを参照して自分の環境でAndroid+OpenCV2.2をセットアップしてみて簡単なエッジ効果を試してみたのを今日まとめてみた。

1. 事前に確認するUtility

「swig」、「swig-java」、「apache-ant」、「cmake」
自分の環境で入ってなかったらインストールしておく。
僕はMacPortsからインストールしました。
$ sudo port install swig
$ sudo port install swig-java
$ sudo port install cmake
「swig」と「swig-java」のactiveバージョンが合わないとエラーになるので、
activeバージョンを合わせ

2. NDK

http://developer.android.comで落とした「ndk r4」ではC++の問題で動かないらしい。
(r5はC++サポートしているのでいけるかなと思ったら、ビルド方法が面倒でやめた。)

「http://www.crystax.net/android/ndk-r4.php」サイトで
C++サポートするようにカスタマイズされた Android NDK r4 を落とす。

ndkが「$HOME/android-ndk-r4-crystax」じゃないとダメらしい。
気に入らないが $HOMEにリンクを作る。

3. OpenCV2.2

OpenCVソース取得。
参照サイトにはSVNから落とすように書いてあるが、ビルドで失敗する可能性があるので、
2.2の安定バージョンのソースを落とした。「http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.2/」

落としたのを好きな場所に解凍してビルドする。

OpenCV Wikiのビルド手順
$ cd opencv/android
$ mkdir build
$ cd build
$ cmake ..
$ make

4. android-jni

Android NDKで使用する「android-opencv」を生成する。
$ cd opencv/android/android-jni
$ make
実行後、生成された「local.env.mk」ファイルの
「ANDROID_NDK_ROOT」項目を自分の環境に合わせて変更して、もう一回「make」(hironemu's blog参照)

「opencv/android/android-jni/libs」に
「armeabi/libandroid-opencv.so」、「armeabi-v7a/libandroid-opencv.so」ファイルができたら成功。



5. エッジ効果を試す。

エッジ効果をテストしたアプリのスクリーンショットはこちら。
元の画像
エッジ効果した画像
問題なく動くが、やはり実機でしか動かなかった。

OpenCVアプリを作るときは
OpenCV Wikiに書いてあるように「project_create.sh」を実行するか
自分で作るなら、NDKの設定で「Android.mk」にOpenCVのライブラリとヘッダのパスを追加する。
#Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := OpenCVUtil
LOCAL_SRC_FILES := babukuma_opencv_util.c
LOCAL_LDLIBS    := -lm -llog

#define OPENCV_INCLUDES and OPENCV_LIBS
PATH_TO_OPENCV_ANDROID_BUILD := ~/dev/OpenCV-2.2.0/android/build
include $(PATH_TO_OPENCV_ANDROID_BUILD)/android-opencv.mk

LOCAL_LDLIBS += $(OPENCV_LIBS)
    
LOCAL_C_INCLUDES +=  $(OPENCV_INCLUDES) 

include $(BUILD_SHARED_LIBRARY)
これなら問題なく「ndk-build」でビルドされる。

以下は作ったソース。。
/**
 * OpenCVUtil.java
 */
package com.babukuma.android.demo.opencv.jni;

/**
 * @author babukuma
 * 
 */
public final class OpenCVUtil {
 static {
  System.loadLibrary("OpenCVUtil");
 }

 /**
  * エッジ効果。
  * 
  * @param picData
  *            RGBのピクセルデータ
  * @param width
  *            画像のWidth
  * @param height
  *            画像のHeight
  */
 public static native void edge(int[] picData, int width, int height);
}
/**
 * EdgeActivity.java
 */
package com.babukuma.android.demo.opencv.activity;

import static com.babukuma.android.demo.opencv.Main.LOG_TAG;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;

import com.babukuma.android.demo.opencv.R;
import com.babukuma.android.demo.opencv.jni.OpenCVUtil;

/**
 * エッジ効果テスト用Activity
 * 
 * @author babukuma
 */
public class EdgeActivity extends Activity {
 private ImageView picView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  Log.d(LOG_TAG, "EdgeActivity#onCreate");

  setContentView(R.layout.edge);

  picView = (ImageView) findViewById(R.id.picView);
  picView.setOnClickListener(new OnClickListener() {

   public void onClick(View v) {
    Log.d(LOG_TAG, "picView#1onClick");
    BitmapDrawable db = (BitmapDrawable) picView.getDrawable();
    Bitmap bitmap = db.getBitmap();
    // Bitmap.Config.ARGB_8888
    Bitmap copyBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
    int width = copyBitmap.getWidth();
    int height = copyBitmap.getHeight();
    int[] pixels = new int[width * height];
    copyBitmap.getPixels(pixels, 0, width, 0, 0, width, height);

    Log.d(LOG_TAG, "OpenCVUtil#edge");
    OpenCVUtil.edge(pixels, width, height);

    Log.d(LOG_TAG, "finish OpenCVUtil#edge");
    copyBitmap.setPixels(pixels, 0, width, 0, 0, width, height);

    picView.setImageBitmap(copyBitmap);
   }
  });
 }
}
/*
 * babukuma_opencv_util.h
 */
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_babukuma_android_demo_opencv_jni_OpenCVUtil */

#ifndef _Included_com_babukuma_android_demo_opencv_jni_OpenCVUtil
#define _Included_com_babukuma_android_demo_opencv_jni_OpenCVUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_babukuma_android_demo_opencv_jni_OpenCVUtil
 * Method:    edge
 * Signature: ([III)V
 */
JNIEXPORT void JNICALL Java_com_babukuma_android_demo_opencv_jni_OpenCVUtil_edge
  (JNIEnv *, jclass, jintArray, jint, jint);

#ifdef __cplusplus
}
#endif
#endif
/*
 * babukuma_opencv_util.c
 */
#include <stdio.h>

// JNI
#include<jni.h>

// Android
#include <android/log.h>

// OpenCV
#include <opencv/cv.h>

#include "babukuma_opencv_util.h"

// Android LOG
#define  LOG_TAG    "OpenCVDemo"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

// 関数定義
IplImage* pixels2IplImage(int* pixels, int width, int height);
void iplImage2Pixcels(int *pixcels, IplImage *srcImage);


/*
 * エッジ効果。
 * 「picData」データは必ず「ARGB」
 *
 * Class:     com_babukuma_android_demo_opencv_jni_OpenCVUtil
 * Method:    edge
 * Signature: ([III)V
 */
JNIEXPORT void JNICALL Java_com_babukuma_android_demo_opencv_jni_OpenCVUtil_edge
  (JNIEnv *env, jclass class, jintArray picData, jint width, jint height)
{
 LOGD("call Java_com_babukuma_android_demo_opencv_jni_OpenCVUtil_edge");

 jboolean isCopy;

 //Colorの配列を取り出す(配列のポインタを取得)
 jint* picDataPtr = (*env)->GetIntArrayElements(env, picData, &isCopy);

 //Color(int) の配列から、IplImageを作る
 LOGD("call pixels2IplImage");
 IplImage *srcImage = pixels2IplImage(picDataPtr, width, height);

 //画像の作成完了。
 LOGD("CV_BGR2GRAY");
 IplImage *wordImage=cvCreateImage(cvGetSize(srcImage),IPL_DEPTH_8U,1);
 cvCvtColor(srcImage, wordImage, CV_BGR2GRAY);
 LOGD("cvReleaseImage srcImage");
 cvReleaseImage(&srcImage);
 srcImage = NULL;

 // Detect edge
 LOGD("Detect edge");
 IplImage *wordImage2 = cvCreateImage(cvGetSize(wordImage), IPL_DEPTH_8U, 1);
 cvCanny(wordImage, wordImage2, 64, 128, 3);
 cvReleaseImage(&wordImage);
 LOGD("cvReleaseImage wordImage");
 cvReleaseImage(&wordImage);
 wordImage = NULL;


 // Convert black and whilte to 24bit image then convert to UIImage to show
 IplImage *edgedImage = cvCreateImage(cvGetSize(wordImage2), IPL_DEPTH_8U, 3);
 int y, x;
 for(y=0; y<wordImage2->height; y++) {
  for(x=0; x<wordImage2->width; x++) {
   char *p = edgedImage->imageData + y * edgedImage->widthStep + x * 3;
   *p = *(p+1) = *(p+2) = wordImage2->imageData[y * wordImage2->widthStep + x];
  }
 }
 LOGD("cvReleaseImage wordImage2");
 cvReleaseImage(&wordImage2);
 wordImage2 = NULL;

 //IplImageの値を、int配列に戻す
 LOGD("call iplImage2Pixcels");
 iplImage2Pixcels(picDataPtr, edgedImage);

 LOGD("cvReleaseImage edgedImage");
 cvReleaseImage(&edgedImage);
 edgedImage = NULL;

 (*env)->ReleaseIntArrayElements(env, picData, picDataPtr, 0);
}

// jint配列からIplImageを作成
// alphaは捨てる。
IplImage* pixels2IplImage(int *pixels, int width, int height) {
 int x, y, index;

 IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
 unsigned char* base = (unsigned char*) (img->imageData);
 unsigned char* ptr;

 for (y = 0; y < height; y++) {
  ptr = base + y * img->widthStep;
  for (x = 0; x < width; x++) {
   index = x + y * width;
   // B
   ptr[3 * x] = pixels[index] & 0xFF;
   // G
   ptr[3 * x + 1] = pixels[index] >> 8 & 0xFF;
   // R
   ptr[3 * x + 2] = pixels[index] >> 16 & 0xFF;
   // A
   // pixels[index] >> 24 & 0xFF;
  }
 }
 return img;
}

// IplImageからjint配列作成
void iplImage2Pixcels(int *pixcels, IplImage *srcImage)
{
    int x, y;
    int w,h;
    w=srcImage->width;
    h=srcImage->height;

    unsigned char* base = (unsigned char*) (srcImage->imageData);
    unsigned char* ptr;
    for (y = 0; y < h; y++)
    {
        ptr = base + y * srcImage->widthStep;
        for (x = 0; x < w; x++)
        {
            pixcels[x + y * w] =
              (0xFF000000) | // A
              (ptr[3 * x + 2] << 16) | // R
              (ptr[3 * x + 1] << 8) | // G
              (ptr[3 * x]); // B
        }
     }
}

彼女もエッジ効果させてみました。
怖い彼女になった。

2010年12月9日木曜日

Android SDK2.3で「Multiple substitutions specified in non-positional」エラーが発生するようになった。

Android SDK2.3をインストルしたら
既存プロジェクト「strings.xml」で「Multiple substitutions specified in non-positional」エラーが発生するようになった。

を調べてみたら、
気になったのが「Formatting strings」の部分。。

僕が作った「strings.xml」の中で
「〜〜〜60~70%です。〜〜〜」という文言がある。

原因は「%」だった。
「%」はどう書けばいいのかな?
「%%」、「\%」はダメだった。。
わからん。。(´Д`;)

とりあえず、この「%」を全角「%」に書き換えたら直った。(^_^;)

2010年11月28日日曜日

ギャラクシータブエミュレータをインストルしてみた。

ギャラクシータブエミュレータをインストルしてみた。

参照サイトは「http://innovator.samsungmobile.com/galaxyTab.do」

「Android SDK and AVD Manager」を開いて、


「Available Packages」タブに
「http://innovator.samsungmobile.com/android/repository/srepository.xml」サイトを追加。


追加後 「GALAXY Tab Addon」をインストル。




ギャラクシータブエミュレータを追加




実行してみると
僕のPCでもはエミュレータ画面が切れてしまいますね。
iPadエミュレータみたいに50%縮小して見れるならいいと思いますが。。

갤럭시탭 에뮬레이터를 설치해보자.

갤럭시탭 에뮬레이터를 설치해보자.

참고 사이트는 「http://innovator.samsungmobile.com/galaxyTab.do

Android SDK and AVD Manager를 열고,


Available Packages에
「http://innovator.samsungmobile.com/android/repository/srepository.xml」사이트를 추가.


추가후 「GALAXY Tab Addon」을 설치.




애뮬레이터 설치.




실행해보니.
제 컴퓨터에서는 한화면에 안보이는군요.
iPad 애뮬레이터처럼 50%로 축소해서 볼 수 있으면 좋을 듯 하지만 좀 아쉽군요.

2010年9月3日金曜日

[Android] お前の体重を見ろ! v1.0

「お前の体重を見ろ!」の1.0バージョンをリリースした。
0.9バージョンはこちら

「お前の体重を見ろ!」は、体重管理アプリケーションです。毎日体重を記録してグラフに表示したり、BMI・BMR計算をすることができます。

Support languages
- English
- 日本語
- 한국어

v1.0
1. 共有機能追加
- メールやツイッタークライアントと連携
(勇気を持ってツイッターに公開可能!!)
2. CSVインポート機能追加
3. アイコン変更

次のバージョンでは要望もあったしロック機能を追加しようかと思ってる。






[Android] 니 몸무게를 봐라! v1.0

「니 몸무게를 봐라!」v1.0를 릴리스하였다.
「니 몸무게를 봐라!」는 간단한 체중관리 무료 안드로이드 어플이다.

Support languages
- English
- 日本語
- 한국어

v1.0의 변경점은 (전 버젼 v9.0 링크)
1. 공유기능추가
- 메일 또는 트위터 클라이언트와 연동
(용감하게 자신의 몸무게 그래프를 공개가능 ^^;)
2. CSV가져오기 기능 추가.
3. 아이콘 변경

다음번에는 사용자들 요청도 있고해서 잠금기능을 추가할까 생각중이다.







2010年9月1日水曜日

[Android] ログレベル設定方法

Androidでログのレベル設定方法

エミュレータと実機のログレベルがどうやらデフォルト「INFO」らしい。

確認してみると

Log.isLoggable(TAG, Log.VERBOSE) == false
Log.isLoggable(TAG, Log.DEBUG) == false
Log.isLoggable(TAG, Log.INFO) == true
Log.isLoggable(TAG, Log.WARN) == true
Log.isLoggable(TAG, Log.ERROR) == true

になる。

だから以下のコードは出力されるが、

Log.d(TAG, msg); // ログレベルとは関係なく出力はされる。



以下のコードだと出力されない。

if(Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, msg); // ログレベルが「DEBUG」以上の場合、出力はされる。
}


特定ログタグのログレベル設定方法は

$ ./adb shell setprop log.tag.<your_log_tag> <level>



例えば、TAGが「BABUKUMA」の場合は

$ ./adb shell stop
$ ./adb shell setprop log.tag.BABUKUMA DEBUG
$ ./adb shell start


確認してみると

Log.isLoggable(TAG, Log.VERBOSE) == false
Log.isLoggable(TAG, Log.DEBUG) == true
Log.isLoggable(TAG, Log.INFO) == true
Log.isLoggable(TAG, Log.WARN) == true
Log.isLoggable(TAG, Log.ERROR) == true

[Android] 로그 레벨 설정방법

Android 로그 레벨 설정방법

에뮬레이터와 단말기의 로그레벨이 아무래도 기본 「INFO」인듯하다.

테스트해보면


Log.isLoggable(TAG, Log.VERBOSE) == false
Log.isLoggable(TAG, Log.DEBUG) == false
Log.isLoggable(TAG, Log.INFO) == true
Log.isLoggable(TAG, Log.WARN) == true
Log.isLoggable(TAG, Log.ERROR) == true



그렇기 때문에 아래와 같은 경우는 로그가 출력되지만,

Log.d(TAG, msg); // 로그레벨과 상관없이 출력됨.



다음의 코드는 출력되지 않는다.

if(Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, msg); // 로그레벨이 「DEBUG」이상인 경우, 출력됨.
}


특정 로그태그의 로그레벨을 설정하는 방법은

$ ./adb shell setprop log.tag.<your_log_tag> <level>



예를 들어 TAG가 「BABUKUMA」인 경우는

$ ./adb shell stop
$ ./adb shell setprop log.tag.BABUKUMA DEBUG
$ ./adb shell start


다시 테스트해본 결과는

Log.isLoggable(TAG, Log.VERBOSE) == false
Log.isLoggable(TAG, Log.DEBUG) == true
Log.isLoggable(TAG, Log.INFO) == true
Log.isLoggable(TAG, Log.WARN) == true
Log.isLoggable(TAG, Log.ERROR) == true

2010年8月12日木曜日

[Android] INSTALL_PARSE_FAILED_NO_CERTIFICATES

アンドロイドアプリで開発したアプリを端末にインストルするとき
INSTALL_PARSE_FAILED_NO_CERTIFICATES」エラーが出てインストルできなくなった。

開発モードアプリケーションへの署名問題らしいけど、
アンインストールして再インストールしても失敗して悩んだ。

原因まではまだわからないが、
パケージ名を変えたらインストルできるようになった。

原因はなんだろ。。。
開発途中で何回かアプリ名を変えたりパケージ名を変えたりしたのが原因かな?

2010年8月5日木曜日

[Android] お前の体重を見ろ! v0.9

今日「お前の体重を見ろ!」の0.9バージョンをアップした。
「お前の体重を見ろ!」は簡単に体重管理できるアンドロイド用の無料アプリだ。
無料だから気楽に使って欲しい!

今回のバージョンアップ内容は
v0.9
1. 体脂肪グラフ追加
2. BMIとBMRの説明追加
3. バグ対応
- 体重グラフで(kg)しか表示されないバグ









次はCSVインポート機能等を追加する予定。

[Android] 니 몸무게를 봐라! v0.9

오늘 「니 몸무게를 봐라!」v0.9를 업데이트하였다.
「니 몸무게를 봐라!」는 간단한 체중관리 무료 안드로이드 어플이다.

v0.9
1. 체지방그래프 추가
2. BMI와 BMR 용어설명 추가
3. 버그수정
- 체중그래프에 (kg)만 표시되는 버그







다음에는 CSV파일 가져오기를 추가해야겠다.

2010年3月11日木曜日

[Android] 「Android NDK r3」を使ってみた。

今回リリースされた「Android NDK r3」を使ってみた。

環境:Mac OS X 10.6.2

android-ndk-r3-darwin-x86.zipを「http://developer.android.com/」からダウンロードして適当に展開する。
おれは「/Users/babukuma/dev/android-ndk-r3」にした。(以下$NDK)

1. Androidプロジェクト生成
テスト用のプロジェクトを生成する。

生成するとこの構成になるはず。

「jni」フォルダ作成


2.「Application.mk」ファイル作成。
プロジェクトディレクトリ下に「Application.mk」ファイルを作成。

今回はモジュール名を「jnitest」にした。
書き方は「$NDK/docs/APPLICATION-MK.TXT」参照

# Application.mk
APP_PROJECT_PATH := $(call my-dir)
APP_MODULES := jnitest


3. Nativeメソッド作成。
「Main.java」ファイルに作成した。

package com.babukuma.android.test.jni;

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

public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

public native String helloJNI();

public native int add(int a, int b);
}


4. ヘッダファイル生成
プロジェクトディレクトリで「javah」コマンドでヘッダファイル「jni/jnitest.h」を生成。

生成された「jnitest.h」ファイル

/* DO NOT EDIT THIS FILE - it is machine generated */
#include<jni.h>
/* Header for class com_babukuma_android_test_jni_Main */

#ifndef _Included_com_babukuma_android_test_jni_Main
#define _Included_com_babukuma_android_test_jni_Main
#ifdef __cplusplus
extern"C" {
#endif
/*
* Class: com_babukuma_android_test_jni_Main
* Method: helloJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_babukuma_android_test_jni_Main_helloJNI
(JNIEnv *, jobject);

/*
* Class: com_babukuma_android_test_jni_Main
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_babukuma_android_test_jni_Main_add
(JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif


5. Cソース作成。
「jni」ディレクトリで「jnitest.c」を作成する。

作った「jnitest.c」ファイル

#include<jni.h>
#include"jnitest.h"

JNIEXPORT jstring JNICALL Java_com_babukuma_android_test_jni_Main_helloJNI(
JNIEnv *env, jobject thisObj) {
jstring result = (*env)->NewStringUTF(env, "Hello JNI !");
return result;
}

JNIEXPORT jint JNICALL Java_com_babukuma_android_test_jni_Main_add(JNIEnv *env,
jobject thisObj, jint a, jint b) {
jint result = a + b;
return result;
}


6. 「Android.mk」ファイルを作成する。
jniディレクトリに「Android.mk」ファイルを作成する。
書き方は「$NDK/docs/ANDROID-MK.TXT」参照

作った「Android.mk」ファイル

# Android.mkLOCAL_PATH := $(call my-dir)

include$(CLEAR_VARS)

LOCAL_MODULE := jnitest
LOCAL_SRC_FILES := jnitest.c

include$(BUILD_SHARED_LIBRARY)


7. Cソースビルド
ビルドをするにはプロジェクトPATHが「$NDK/apps/<プロジェクト>」になる必要があるのでリンクを作った。

$NDKディレクトリで「make APP=jnitest」でビルド
ここで「jnitest」は「$NDK/apps/」下のプロジェクトフォルダ名になる。

Eclipseをリロードしてみると「libs/armeabi/libjnitest.so」ファイルが生成されたのがわかる。


8. Javaソースを修正して実行してみる。
修正後の「Main.java」ファイル

package com.babukuma.android.test.jni;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class Main extends Activity {
static {
System.loadLibrary("jnitest");
}

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// call helloJNI()
TextView result1 = (TextView) findViewById(R.id.text_result_1);
result1.setText(helloJNI());

// call add(1, 2)
TextView result2 = (TextView) findViewById(R.id.text_result_2);
result2.setText("1 + 2 = " + add(1, 2));
}

public native String helloJNI();

public native int add(int a, int b);
}


修正後実行してみるとNativeメソッドが問題なく呼ばれた。