Return to Tech/other

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

Return to Tech/other