Android
androidメモ
環境設定・プロジェクト作成方法等
サンプル apk(debug版署名のもの..)がダウンロード可能です
サンプルアプリケーション chat
チャットクライアントのサンプルです
このサイトを webviewで表示させるだけ..
WebViewのサンプル
プロジェクトを作成します
android create project -t 6 -p ./ -k localdomain.localhost -a wview
src/localdomain/localhost/wview.java を少し修正
import android.webkit.WebView; を追加
--- file:wv/src/localdomain/localhost/wview.java
package localdomain.localhost;
import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebView;
public class wview extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// ウェブビューのインスタンスを生成
WebView wv = new WebView(this);
//
//setContentView(R.layout.main);
setContentView(wv);
wv.loadUrl("http://tera.sytes.net/");
}
}
--- file:wv/AndroidManifest.xml
</application>の下に下記を追加
<uses-permission android:name="android.permission.INTERNET"/>
※この記述を追加することでインターネットへのアクセスが可能となります。
※エミュレータでしか試していませんが...
ant debug でビルドします
adb install -r bin\wview-debug.apk でデバイスに転送...
実行例
NDKについて
Android 2.3.3から NativeActivity を利用することで
javaではなく c言語でアプリケーションを作成できるようになりました。
方法
AndroidManifest.xml を下のように記述します
file:AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android:"http://schemas.android.com/apk/res/android"
package="localdomain.NativeActivity"
android:versionCode="1"
android.versionName="1.0">
<application android:label="@string/app_name" android:icon="@drawable/icon">
<activity androd:name="android.app.NativeActivity"
android:label="@string/app_name">
<meta-data android:name="android.app.lib_name"
android:value="native-main" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
---
srcディレクトリではなく jniディレクトリを作成し
メイクファイルとソースファイルを用意します。
メイクファイルは jni/Android.mk
ソースファイルは jni/main.cpp
sdkと大分環境が変わり
main.cppに android_main() を記述していく形になります。
※androidのactivity経由でのapiが利用できない、利用方法に違いがでます。
※大きなメリットとしては c/c++のライブラリが流用可能なことでしょうか
あとで mainのソースをのせます
--- file:jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := native-main
LOCAL_SRC_FILES := main.cpp hogehoge.cpp hogehoge2.cpp
LOCAL_LDLIBS := -lm -llog -landroid -lEGL -lGLESv1_CM
LOCAL_STATIC_LIBRARIES := android_native_app_glue bullet
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
$(call import-module,android/bullet)
--- file:jni/main.cpp
#include <jni.h>
#include <errno.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <math.h>
#include <android/sensor.h>
#include <android/log.h>
#include <android/asset_manager.h>
#include <android_native_app_glue.h>
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> // read..
#include "bullet/btBulletDynamicsCommon.h"
#include "bullet/LinearMath/btAlignedObjectArray.h"
#include "bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
#include "bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
#include "bullet/LinearMath/btHashMap.h"
#define LOG_TAG "hogehoge"
#define POINT_MAX (5)
static char *Pointer;
static char Token[1024];
typedef struct _TouchPoint {
int32_t x;
int32_t y;
} TouchPoint;
typedef struct _saved_state {
TouchPoint point[POINT_MAX];
} saved_state;
struct engine {
struct android_app *app;
ASensorManager *sensorManager;
const ASensor *accelerometerSensor;
ASensorEventQueue *sensorEventQueue;
int animating;
EGLDisplay display;
EGLSurface surface;
EGLContext context;
int32_t width;
int32_t height;
saved_state state;
};
static int engine_init_display(struct engine *engine)
{
const EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
};
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);
source = eglCreateWindowSurface(display, config, engine->app->window, NULL);
context = eglCreateContext(display, config, NULL, NULL);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
engine->display = display;
engine->context = context;
engine->surface = surface;
engine->width = w;
engine->height = h;
return 0;
}
static void engine_draw_frame(struct engine *engine)
{
if (engine->app->window == NULL)
{
return;
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLookAt(cameraPos.getX(), cameraPos.getY(), cameraPos.getZ(),
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
// draw
eglSwapBuffers(engine->display, engine->surface);
}
static int engine_term_display(struct engine *engine)
{
if (engine->display != EGL_NO_DISPLAY)
{
eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
if (engine->context != EGL_NO_CONTEXT)
{
eglDestroyContext(engine->display, engine->context);
}
if (engine->surface != EGL_NO_SURFACE)
{
eglDestroySurface(engine->display, engine->surface);
}
eglTerminate(engine->display);
}
engine->animating = 0;
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
}
static int32_t engine_handle_input(struct android_app *app, AInputEvent *event)
{
struct engine *engine = (struct engine*)app->userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
{
size_t count = AMotionEvent_getPointerCount(event);
for(int i = 0; i < count; i++)
{
engine->state.point[i].x = AMotionEvent_getX(event, i);
engine->state.point[i].y = AMotionEvent_getY(event, i);
/*
LOGI("PointerCount: %d x:%d y:%d",
i,
engine->state.point[i].x,
engine->state.point[i].y );
*/
}
return 1;
}
return 0;
}
static void engine_handle_cmd(struct android_app *app, int32_t cmd)
{
struct engine *engine = (struct engine*)app->userData;
switch (cmd)
{
case APP_CMD_SAVE_STATE:
engine->app->savedState = malloc(sizeof(saved_state));
*((saved_state*)engine->app->savedState) = engine->state;
engine->app->savedStateSize = sizeof(saved_state);
break;
case APP_CMD_INIT_WINDOW:
if (engine->app->window != NULL)
{
engine->animating = 1;
engine_init_display(engine);
engine_draw_frame(engine);
}
break;
case APP_CMD_TERM_WINDOW:
engine_term_display(engine);
break;
case APP_CMD_GAINED_FOCUS:
if (engine->accelerometerSensor != NULL)
{
engine->animating = 1;
ASensorEventQueue_enableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
ASensorEventQueue_setEventRate(engine->sensorEventQueue,
engine->accelerometerSensor, (1000L/60)*1000);
}
break;
case APP_CMD_LOST_FOCUS:
if (engine->accelerometerSensor != NULL)
{
ASensorEventQueue_disableSensor(engine->sensorEventQueue,
engine->accelerometerSensor);
}
engine->animating = 0;
engine_draw_frame(engine);
break;
}
}
void android_main(struct android_app* state)
{
struct engine engine;
// おまじない
app_dummy();
memset(&engine, 0, sizeof(engine));
state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state;
engine.sensorManager = ASensorManager_getInstance();
engine.accelerometerSensor = ASensorManager_getDefaultSensor(
engine.sensorManager, ASENSOR_TYPE_ACCELEROMETER);
engine.sensorEventQueue = ASensorManager_createEventQueue(
engine.sensorManager, state->looper, LOOPER_ID_USER, NULL, NULL);
if (state->saveState != NULL)
{
engine.state = *(saved_state*)state->savedState;
}
// アセットマネージャーを取得
AAssetManager *assetManager = state->activity->assetManager;
if (NULL != assetManager)
{
LOGI("AAssetManager is enabled\n");
}
// objなにかしら.Load(assetManager, (char*)"なにかしら.x");
//
while (1)
{
int ident;
int events;
struct android_poll_source *source;
while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
(void**)&source))) >= 0)
{
if (source != NULL)
{
source->process(state, source);
}
if (ident == LOOPER_ID_USER)
{
if (engine.accelerometerSensor != NULL)
{
ASensorEvent event;
while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
&event, 1) > 0)
{
}
}
}
if (state->destroyRequested != 0)
{
engine_term_display(&engine);
return;
}
}
if (engine.animating)
{
engine_draw_frame(&engine);
}
}
}
---
ビルドは プロジェクト直下にて ndk-build
その後 ant-debug
デバイスへのインストールは adb install -r bin\アプリ.apk
OpenGL ES(1系)を少々お試し.
AndroidProjectのビルドターゲットは 2.1-update1となります。
トライアングルの表示例
今回利用するソースファイル(GLES10Activity.java, GLES10Renderer.java)
androidのアクティビティを継承した GLES10Activityおよび
GLSurfaceViewのレンダラーインターフェースを実装した GLES10Rendererを利用します。
About OpenGL ES