Android

Androidでお電話

久しぶりに技術ネタを書こうかと。

Androidといえばコンテストでうまくいくと賞金がもらえることでおなじみですが、 なんと電話がかけられるそうです。

IServiceManager sm = ServiceManagerNative.getDefault();
IPhone phone = IPhone.Stub.asInterface(sm.getService("phone"));
phone.call("911");

これはドキュメントに載っていたコードを丸パクリなのですが、なにがすごいって 公式サイトのドキュメントにIServiceManagerが存在しない。すごい。でもちゃんと動く。 で、IPhoneにはcallとdialの2つのメソッドがあるのですが、違いはcallはもう直で電話する のに対して、dialはdialerに電話番号を入力するところまで。 つまりこのcallを利用して、dialerアプリが作れます。

All applications are equal って公式サイトのトップに書いてある通りですね。

| | コメント (0) | トラックバック (0)

AndroidSDK感想

前項で紹介した通り、昨日(?)公開されたばかりのNew Version AndroidSDKですが、軽く触って見た感想を適当に書いてみます。

  • ちょいちょい使ってたメソッドが消えててびっくりした(canvas.getPixels()とか)
  • PackageManager用の新しいパッケージができてた。
  • 上記に関連して、ActivityInfoとかが内部クラスじゃなくなってた
  • OpenGLESにTextureクラスが追加されたけど、なんか自分で作ったやつとあんま変わらんっぽい
  • ContentURIがUri.なんたらとかいう感じに変わってた
  • っていうことはContentProviderとか使ってるやつ結構書き換えないといけない感じ?
  • AndroidManifest.xmlの書き方が変わった。
  • 新しいメディアフォーマットに対応
  • なんだかそういう感じの変更点多数
  • 巷では新しいホームスクリーンが話題
  • Geo-coding対応

特に大々的な変更点はなさそうな印象。(気付いていないだけかもしれません)あとはバグがなくなったりもしているらしい。メソッドの名前変更とか、パッケージ切り出し等の変更が目立った。あと、新しいホームスクリーンって別にそんなすごくない気がする。だってホームスクリーン自分で作れるしね。またなんか気がついたら書きます。

| | コメント (0) | トラックバック (0)

Androidがバージョンアップ!!

公式ブログでも宣言のあったAndroidの大幅バージョンアップですが、ついに公開された模様です

ちょっくらダウンロード&インストールして参ります。

| | コメント (0) | トラックバック (0)

まとめてみた-。

期末テストも一段落ついたことだし、ここらで一つAndroidについてまとめてみるかなーって ことで、適当にまとめてみました。

デザインも内容もとりあえず大分適当。とりあえずバージョン0.3くらいということで。

http://chephes.sakura.ne.jp/android/

とりあえず随時進化させていくので、たまに見てみてください

| | コメント (0) | トラックバック (0)

Androidの非公式実機が登場!

Androidでの開発は非常に面白いが、やはり残念なのが実機が無いということである。 しかしeu.edgeさんによると、ザウルスのSL-C760でAndroidが動いたそうである。

タッチスクリーンは動いていないものの、キーボードは動いており、アプリケーションも動く模様。

今後のレポートに期待。

| | コメント (0) | トラックバック (0)

AndroidのOpenGL ESでマウスピッキング 〜完結編〜

AndroidのOpenGL ESでのマウスピッキングについに成功しました。

前回の物では、マウス座標と3D空間の関連付けを自前の関数でやっていたのですが、 それにバグがあり、視点の位置によってはうまくいかないことがありました。

そこで利用したのがこの関数。

GLU.gluUnProject

これがもう便利べんり。あとはあたり判定は実装済みだったので、置き換えて完了。

使い方は大体以下の通り。

    	int[] bits = new int[16];
    float[] model = new float[16];
    float[] proj = new float[16];
    gl.glGetIntegerv(gl.GL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, bits, 0);
    for(int i = 0; i < bits.length; i++){
    model[i] = Float.intBitsToFloat(bits[i]);
    }
    ((GL11)gl).glGetIntegerv(gl.GL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS_OES, bits, 0);
    for(int i = 0; i < bits.length; i++){
    proj[i] = Float.intBitsToFloat(bits[i]);
    }
   
    float[] ret = new float[3];
    GLU.gluUnProject((float)curX, (float)curY, 0f, model, 0, proj, 0, new int[]{0, 0, getWidth(), getHeight()}, 0, ret, 0);
    int x = (int)(ret[0] * 0x10000);
    int y = (int)(ret[1] * 0x10000);
    int z = (int)(ret[2] * 0x10000);

これでx、y、zにクリックされた点の座標が格納されるので、それとカメラ位置を通る 直線の式を計算し、それがポリゴンと衝突するかを判定すればOK

以下あたり判定のソース

package net.chephes.opengl;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

import net.chephes.math.Matrix3D;

public class Plane{
    protected ByteBuffer  mIndexBuffer;
    protected IntBuffer   mVertexBuffer;
    protected int x, y, z;
    protected int rotateX, rotateY, rotateZ;
    protected int width, height;

    protected int one = 0x10000;
    protected int vertices[] = {
           -one, one, 0,
            one, one, 0,
            one,  -one, 0,
           -one,  -one, 0,
        };
       
    protected byte indices[] = {
            0, 1, 2,    2, 3, 0
    };
   
    public Plane(){
    this(1, 1);
    }
   
    public Plane(int width, int height){
    for(int i = 0; i < vertices.length; i+=3){
    vertices[i] *= width;
    vertices[i+1] *= height;
    }
    mVertexBuffer = GLUtil.createIntBuffer(vertices);
    mIndexBuffer = GLUtil.createByteBuffer(indices);
    }
   
    public void setX(int x){
    this.x = x;
    for(int i = 0; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + x);
    }
    }
   
    public void setY(int y){
    this.y = y;
    for(int i = 1; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + y);
    }
    }
   
    public void setZ(int z){
    this.z = z;
    for(int i = 2; i < vertices.length; i+=3){
        mVertexBuffer.put(i, vertices[i] + z);
    }
    }
   
    public void setRotateX(int rotateX){
    this.rotateX = rotateX;
    double theta = rotateX * Math.PI / 0x10000;
    double cos = Math.cos(theta);
    double sin = Math.sin(theta);
    for(int i = 1; i < vertices.length; i+=3){
    double y = (double)(vertices[i]) / 0x10000;
    double z = (double)(vertices[i+1]) / 0x10000;
    int flagY = y > 0 ? 1 : -1;
    double r = Math.sqrt(y * y + z * z);
        mVertexBuffer.put(i,
        flagY * (int)(r * cos * 0x10000) + this.y);
        mVertexBuffer.put(i+1,
        - flagY * (int)(r * sin * 0x10000) + this.z);
    }
    }
   
    public void setRotateY(int rotateY){
    this.rotateY = rotateY;
    double theta = rotateY * Math.PI / 0x10000;
    double cos = Math.cos(theta);
    double sin = Math.sin(theta);
    for(int i = 0; i < vertices.length; i+=3){
    double x = (double)(vertices[i]) / 0x10000;
    double z = (double)(vertices[i+2]) / 0x10000;
    int flagX = x > 0 ? 1 : -1;
    double r = Math.sqrt(x * x + z * z);
        mVertexBuffer.put(i,
        flagX * (int)(r * cos * 0x10000) + this.x);
        mVertexBuffer.put(i+2,
        - flagX * (int)(r *sin * 0x10000) + this.z);
    }
    }
   
    public void setRotateZ(int rotateZ){
    this.rotateZ = rotateZ;
    double theta = rotateZ * Math.PI / 0x10000;
    double cos = Math.cos(theta);
    double sin = Math.sin(theta);
    for(int i = 0; i < vertices.length; i+=3){
    double x = (double)(vertices[i]) / 0x10000;
    double y = (double)(vertices[i+1]) / 0x10000;
    int flagX = x > 0 ? 1 : -1;
    double r = Math.sqrt(x * x + y * y);
        mVertexBuffer.put(i,
        flagX * (int)(r * cos * 0x10000) + this.x);
        mVertexBuffer.put(i+1,
        - flagX * (int)(r * sin * 0x10000) + this.y);
    }
    }
   
    public int getX(){return x;}
    public int getY(){return y;}
    public int getZ(){return z;}
    public int getRotateX(){return rotateX;}
    public int getRotateY(){return rotateY;}
    public int getRotateZ(){return rotateZ;}
   
    public void render(GL10 gl){
    synchronized(gl){
            gl.glColor4f(1f, 1f, 1f, 1f);
            gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
            gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
    }

    }
   
    private boolean isInside(int[] x, int[] y, int[] p, int[] q, int[] r){
    float v[][] = new float[3][3];
    float inv[][];
    for(int i = 0; i < 3; i++){
        v[i][0] = (float)(x[i] - y[i]) / 0x10000;
        v[i][1] = (float)(q[i] - p[i]) / 0x10000;
        v[i][2] = (float)(r[i] - p[i]) / 0x10000;
    }
    try{
        inv = Matrix3D.invert(v);
    }catch(Exception e){
    return false;
    }

    float t = 0, s = 0, u = 0;
    for(int i = 0; i < 3; i++){
    t += inv[0][i] * (float)(x[i] - p[i]) / 0x10000;
    s += inv[1][i] * (float)(x[i] - p[i]) / 0x10000;
    u += inv[2][i] * (float)(x[i] - p[i]) / 0x10000;
    }
    return s >= 0 && u >= 0 && s + u <= 1;
    }
   
    public boolean isInside(int[] x, int[] y){
    int[] p = new int[3];
    int[] q = new int[3];
    int[] r = new int[3];
    for(int i = 0; i < 3; i++){
    p[i] = mVertexBuffer.get(i);
    q[i] = mVertexBuffer.get(3 + i);
    r[i] = mVertexBuffer.get(6 + i);
    }
    boolean ret = isInside(x, y, p, q, r);
    for(int i = 0; i < 3; i++){
    p[i] = mVertexBuffer.get(6 + i);
    q[i] = mVertexBuffer.get(9 + i);
    r[i] = mVertexBuffer.get(0 + i);
    }
   
    return ret || isInside(x, y, p, q, r);
    }
   
}

isInside関数のint[] x、int[] yはそれぞれカメラの座標とクリックされた点の座標。 pqrはそれぞれ三角形の頂点を表す。

なおこのplaneクラスは高レベルオブジェクトとして紹介した物と同一で、 setRotationXしてから移動するとrotationが台無しになるというバグ付き。そのうち直します。

| | コメント (3) | トラックバック (0)

AndroidでSystem.out.println

アプリを開発する上で書かせないのがコンソール出力ですが、Androidでは いつもどおり

System.out.println("hoge");
と書いても出力されません。

そこで、Androidではandroid.util.Logクラスを利用して出力します。

eclipse上で結果を見るときはWindow > Show ViewからAndroidを選び、LogCatを表示するように 設定するだけで見れます。

動作イメージは以下

| | コメント (0) | トラックバック (0)

Androidでゲーム第二弾 ブロック崩し

これはあつい。Schlechte Weltさんがブロック崩しを作ったらしい。 これはもう動かしてみるしか無い、ということでサンプルムービー。

あとニュースといえば、NESエミュが動いたらしいですね。ソースも公開予定らしいので、 勉強になりそう。

| | コメント (1) | トラックバック (0)

AndroidのOpenGL ESでテクスチャ

OpenGL ES系のネタ。せっかくテクスチャも張れるということなので、 ためしに張ってみました。画像読み込み関連はいつものごとくSchlechte Weltさんを参考にしました。

以下サンプルソース

package net.chephes.graphics;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.os.Bundle;
import android.view.*;
import android.graphics.*;
import android.content.Context;
import android.content.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;


public class Android3D extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        View view = new View3D(this);
        setContentView(view);
    }
}

class View3D extends View{
private float angle = 0;
private OpenGLContext glContext;
    private ByteBuffer  mIndexBuffer;
    private IntBuffer   mVertexBuffer;
    private IntBuffer   mColorBuffer;
    private FloatBuffer mTextureBuffer;
    private int texid;
   
    private boolean isDraw = false;
   
    int one = 0x10000;
    int vertices[] = {
           -one, -one, -one,
            one, -one, -one,
            one,  one, -one,
           -one,  one, -one,
        };
       
    int colors[] = {
              0,    0,    0,  one,
            one,    0,    0,  one,
            one,  one,    0,  one,
              0,  one,    0,  one,
        };
    byte indices[] = {
            0, 1, 2,    2, 3, 0
    };

    public View3D(Context context){
super(context);

    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
    vbb.order(ByteOrder.nativeOrder());
    mVertexBuffer = vbb.asIntBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
    cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asIntBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);

mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
glContext = new OpenGLContext(0);
GL10 gl = (GL10)(glContext.getGL());
        gl.glEnable(gl.GL_TEXTURE_2D);
int a[] = new int[1];
gl.glGenTextures(1, a, 0);
texid = a[0];
gl.glBindTexture(gl.GL_TEXTURE_2D, texid);

Canvas canvas = loadImage(R.drawable.kirby, 128, 128);
a = canvas.getPixels();
ByteBuffer tb = ByteBuffer.allocateDirect(a.length * 4);
tb.order(ByteOrder.nativeOrder());
IntBuffer ib = tb.asIntBuffer();
ib.put(a);
ib.position(0);

gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGBA, 128, 128, 0,
gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, ib);

tb = ByteBuffer.allocateDirect(256);
float b[] = {0, 0,
1, 0,
1, 1,
0, 1};
tb.order(ByteOrder.nativeOrder());
mTextureBuffer = tb.asFloatBuffer();
mTextureBuffer.put(b);
mTextureBuffer.position(0);
isDraw = true;
}

public Canvas loadImage(int fileid, int width, int height) {
Resources r = this.getContext().getResources();
Bitmap bitmap = Bitmap.createBitmap(width, height, true);
Drawable drawable = r.getDrawable(fileid);
Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, width, height);
drawable.draw(canvas);

return canvas;
}

    @Override
    protected void onDraw(Canvas canvas) {
    if(!isDraw){ return;}

GL10 gl = (GL10)(glContext.getGL());
glContext.waitNative(canvas, this);

gl.glClear(gl.GL_COLOR_BUFFER_BIT);

        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glScalef(0.8f, 0.8f, 0.8f);
        gl.glRotatef(angle += 1.2f, 1, 1, 0);

        gl.glColor4f(1f, 1f, 1f, 1f);
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
        gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);

    gl.glTexEnvx(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE);

        gl.glDisable(gl.GL_CULL_FACE);

        gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, mTextureBuffer);
        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
        gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
invalidate();
glContext.waitGL();

    }
}

どうやってもテクスチャがはれずに大ハマリしました。とりあえず報告なので、 細かい解説はのちのちやります。リソースは各自適当な物を用意してください。

また、上部にタイトルバーが若干のこってておかしいですが、それの直し方を 知ってる人がいたら、教えてくれると助かります。

11/18追記
requestWindowFeature(Window.FEATURE_NO_TITLE);
でタイトルバー問題は解決。ありがとうs_weltさん

| | コメント (2) | トラックバック (0)

AndroidのOpenGLで3D描画

AndroidではOpenGLを使って3Dを描画できるらしいので、早速使ってみた

以下はただ四角いポリゴンを書くだけの簡単なサンプルです。

OpenGLに関してはwisdomsoftのOpenGL入門を参考にしました。

package net.chephes.graphics;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.graphics.*;
import android.content.Context;

public class Android3D extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(new View3D(this));
    }
}

class View3D extends View{
private float angle = 0;
private OpenGLContext glContext;
    private ByteBuffer  mIndexBuffer;
    private IntBuffer   mVertexBuffer;
    private IntBuffer   mColorBuffer;
    int one = 0x10000;
    int vertices[] = {
           -one, -one, -one,
            one, -one, -one,
            one,  one, -one,
           -one,  one, -one,
        };
       
    int colors[] = {
              0,    0,    0,  one,
            one,    0,    0,  one,
            one,  one,    0,  one,
              0,  one,    0,  one,
        };
    byte indices[] = {
            0, 1, 2,    2, 3, 0
    };

    public View3D(Context context){
super(context);
glContext = new OpenGLContext(0);
    ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
    vbb.order(ByteOrder.nativeOrder());
    mVertexBuffer = vbb.asIntBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);

    ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
    cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asIntBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
}

    @Override
    protected void onDraw(Canvas canvas) {
GL10 gl = (GL10)(glContext.getGL());
glContext.waitNative(canvas, this);

gl.glClear(gl.GL_COLOR_BUFFER_BIT);

        gl.glMatrixMode(gl.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -3.0f);
        gl.glScalef(0.5f, 0.5f, 0.5f);
        gl.glRotatef(angle += 1.2f, 0, 0, 1);

        gl.glColor4f(0.7f, 0.7f, 0.7f, 1.0f);
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
        gl.glEnableClientState(gl.GL_COLOR_ARRAY);
        gl.glDisable(gl.GL_CULL_FACE);

gl.glFrontFace(gl.GL_CW);
        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);
        gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);
        gl.glDrawElements(gl.GL_TRIANGLES, 6, gl.GL_UNSIGNED_BYTE, mIndexBuffer);
invalidate();
glContext.waitGL();
    }
}

OpenGLを以前から利用している人にとっては簡単そう。僕は今回が初めての利用だったので、 いろいろわからずとりあえずこれだけは書いてみた、という感じ。

3Dに関してはなかなか面白そうなので、また別のサンプルを作ったらソースを公開します。

| | コメント (1) | トラックバック (0)

その他のカテゴリー

ActionScript | Android | Cocoa | DSi | WebService | 文房具