ApiDemosを調べる3 - 個別API Animation.Activity

App -> Activity -> Animationについて。
Activity間を遷移する際の表示に動きをつけるもの。
アルファを用いてじわっと出てきたりする。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_animation);

        // Watch for button clicks.
        Button button = (Button)findViewById(R.id.fade_animation);
        button.setOnClickListener(mFadeListener);
        button = (Button)findViewById(R.id.zoom_animation);
        button.setOnClickListener(mZoomListener);
    }

setContentViewはXMLからレイアウトを読み込む。
R.layout.activity_animationはプロジェクトのres/layout/activity_animation.xml以下にある。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:padding="4dip"
    android:gravity="center_horizontal"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent" android:layout_height="wrap_content"
        android:layout_weight="0"
        android:paddingBottom="4dip"
        android:text="@string/activity_animation_msg"/>

    <Button android:id="@+id/fade_animation"
        android:layout_width="wrap_content" android:layout_height="wrap_content" 
        android:text="@string/activity_animation_fade">
        <requestFocus />
    </Button>

    <Button android:id="@+id/zoom_animation"
        android:layout_width="wrap_content" android:layout_height="wrap_content" 
        android:text="@string/activity_animation_zoom">
    </Button>

</LinearLayout>

LinearLayoutは一列に並べるLayout方法。
orientationで垂直方向指定、gravityでcenter揃え。

LinearLayoutの中に3つのWidget(View)が並ぶ。

TextView
 幅は親に合わせて(親=LinearLayout=画面)
 高さはコンテンツにあわせて
 文字はres/values/strings.xmlに定義されている。

    <string name="activity_animation_msg">Press a button to launch an activity with a custom animation.</string>

Button
 幅と高さはコンテンツにあわせて(この場合文字の大きさと数)
 文字は2つのボタンそれぞれについて、

    <string name="activity_animation_fade">Fade in</string>
    <string name="activity_animation_zoom">Zoom in</string>

これで以下のような画面が出力される

XMLからレイアウトを設定した後、今度はそれらの部品を
コードで取得する。findViewById()を用いて、ボタンオブジェクトを取得し、
setOnClickListener()でClickしたときの振る舞いを設定する。

OnClickListener()は以下のように定義する。
ここがこのアプリのポイント。アニメーションによる画面遷移の設定を行っている。

    private OnClickListener mFadeListener = new OnClickListener() {
        public void onClick(View v) {
            // Request the next activity transition (here starting a new one).
            startActivity(new Intent(Animation.this, Controls1.class));
            // Supply a custom animation.  This one will just fade the new
            // activity on top.  Note that we need to also supply an animation
            // (here just doing nothing for the same amount of time) for the
            // old activity to prevent it from going away too soon.
            overridePendingTransition(R.anim.fade, R.anim.hold);
        }
    };

overridePendingTransition()をstartActivity()の直後に呼ぶことで
遷移にAnimation効果を持たせることができる。
第1引数はenterAnim, 第2引数はexitAnimらしい。
enterは新Activityかと。exitは旧Activityかと。

R.anim.fade, R.anim.holdはそれぞれ/res/anim/fade.xml, /res/anim/hold.xml
記載されている。以下のとおり。

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_interpolator"
       android:fromAlpha="0.0" android:toAlpha="1.0"
       android:duration="@android:integer/config_longAnimTime" />

<translate xmlns:android="http://schemas.android.com/apk/res/android"
       android:interpolator="@android:anim/accelerate_interpolator"
       android:fromXDelta="0" android:toXDelta="0"
       android:duration="@android:integer/config_longAnimTime" />
       

interpolatorは遷移の速さを決める。
accelerate_interppolatorはどんどん早くを意味する。
そのほかは
http://developer.android.com/reference/android/R.anim.htmlで。

durationは遷移の時間を決める。
config_longAnimTimeは遅く。時間[ms]での指定もよいらしい。
そのほかは
http://developer.android.com/reference/android/R.integer.htmlで。

Controls1.classは別途定義された適当なActivityを含む。
具体的には以下のとおり。

public class Controls1 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.controls_1);

        Spinner s1 = (Spinner) findViewById(R.id.spinner1);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, mStrings);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        s1.setAdapter(adapter);
    }

    private static final String[] mStrings = {
        "Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"
    };
}

もう1つ、Zoomという遷移がある。

    private OnClickListener mZoomListener = new OnClickListener() {
        public void onClick(View v) {
            // Request the next activity transition (here starting a new one).
            startActivity(new Intent(Animation.this, Controls1.class));
            // This is a more complicated animation, involving transformations
            // on both this (exit) and the new (enter) activity.  Note how for
            // the duration of the animation we force the exiting activity
            // to be Z-ordered on top (even though it really isn't) to achieve
            // the effect we want.
            overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
        }
    };

XMLでZoomの設定をする。

zoom_enter

<!-- Special window zoom animation: this is the element that enters the screen,
     it starts at 200% and scales down.  Goes with zoom_exit.xml. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/decelerate_interpolator">
    <scale android:fromXScale="2.0" android:toXScale="1.0"
           android:fromYScale="2.0" android:toYScale="1.0"
           android:pivotX="50%p" android:pivotY="50%p"
           android:duration="@android:integer/config_mediumAnimTime" />
</set>

zoom_exit

<!-- Special window zoom animation: this is the element that exits the
     screen, it is forced above the entering element and starts at its
     normal size (filling the screen) and scales down while fading out.
     This goes with zoom_enter.xml. -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:anim/decelerate_interpolator"
        android:zAdjustment="top">
    <scale android:fromXScale="1.0" android:toXScale=".5"
           android:fromYScale="1.0" android:toYScale=".5"
           android:pivotX="50%p" android:pivotY="50%p"
           android:duration="@android:integer/config_mediumAnimTime" />
    <alpha android:fromAlpha="1.0" android:toAlpha="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
</set>

新しいほうのActivityは縮小して本来のサイズへ(200% -> 100%)
消えていくほうは縮小(100% -> 50%)しながら薄くなっていく(Alpha 1.0 -> 0.0)。

以上。

ApiDemosを調べる2 - 個別API GLES20Activity

graphics -> OpenGL ES -> OpenGL ES 2.0

で、GLES20Activityを実行します。

public class GLES20Activity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGLSurfaceView = new GLSurfaceView(this);
        if (detectOpenGLES20()) {
            // Tell the surface view we want to create an OpenGL ES 2.0-compatible
            // context, and set an OpenGL ES 2.0-compatible renderer.
            mGLSurfaceView.setEGLContextClientVersion(2);
            mGLSurfaceView.setRenderer(new GLES20TriangleRenderer(this));
        } else {
            // Set an OpenGL ES 1.x-compatible renderer. In a real application
            // this renderer might approximate the same output as the 2.0 renderer.
            mGLSurfaceView.setRenderer(new TriangleRenderer(this));
        }
        setContentView(mGLSurfaceView);
    }

    private boolean detectOpenGLES20() {
        ActivityManager am =
            (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo info = am.getDeviceConfigurationInfo();
        return (info.reqGlEsVersion >= 0x20000);
    }

    @Override
    protected void onResume() {
        // Ideally a game should implement onResume() and onPause()
        // to take appropriate action when the activity looses focus
        super.onResume();
        mGLSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
        // Ideally a game should implement onResume() and onPause()
        // to take appropriate action when the activity looses focus
        super.onPause();
        mGLSurfaceView.onPause();
    }

    private GLSurfaceView mGLSurfaceView;
}

onPause()とonResume()は割愛します。
(Pauseはほかのアプリにフォーカスが移ったときに呼び出される。
 その時の状態を保存したりする。
 Resumeはほかのアプリからまた戻ってきたときに呼び出される。
 以前保存した状態を呼び出したりする。)

onCreate()が呼ばれる。

次にGLSurfaceViewクラスのインスタンスを生成する。

detectOpenGLES20はシステムがGLES2.0に対応しているかどうかを確認する。
自分はエミュレータ上で実行したところ、非対応になってしまった。

(GLES2.0に対応している場合には、EGLContextのバージョンを2に設定してから)
setRendererでRendererを設定する。

setRendererの内部実装は以下のとおり(Android SDKだけではアクセスできないのでソースが必要)

    public void setRenderer(Renderer renderer) {
        checkRenderThreadState();
        if (mEGLConfigChooser == null) {
            mEGLConfigChooser = new SimpleEGLConfigChooser(true);
        }
        if (mEGLContextFactory == null) {
            mEGLContextFactory = new DefaultContextFactory();
        }
        if (mEGLWindowSurfaceFactory == null) {
            mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
        }
        mRenderer = renderer;
        mGLThread = new GLThread(renderer);
        mGLThread.start();
    }

checkRenderThreadStateはすでにmGLThreadが生成されていないかを
確認するもの。

その後、GLSurfaceViewクラスに必要なインスタンス等生成していく。
描画用のThreadを別途生成している。

RendererはGLSurfaceViewの中にinterfaceが書かれている。

    public interface Renderer {
        /**
         * Called when the surface is created or recreated.
         * 
         */
        void onSurfaceCreated(GL10 gl, EGLConfig config);

        /**
         * Called when the surface changed size.
         * @param gl the GL interface. Use <code>instanceof</code> to
         * test if the interface supports GL11 or higher interfaces.
         * @param width
         * @param height
         */
        void onSurfaceChanged(GL10 gl, int width, int height);

        /**
         * Called to draw the current frame.

         * @param gl the GL interface. Use <code>instanceof</code> to
         * test if the interface supports GL11 or higher interfaces.
         */
        void onDrawFrame(GL10 gl);
    }

onSurfaceCreatedは起動時に呼ばれる。
GLの初期化をしたり、画面サイズを設定したりする。
今回は、TriangleRenderer.javaの中で以下の記述がなされている。

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

        gl.glDisable(GL10.GL_DITHER);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);

        gl.glClearColor(.5f, .5f, .5f, 1);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glEnable(GL10.GL_TEXTURE_2D);


        int[] textures = new int[1];
        gl.glGenTextures(1, textures, 0);
        mTextureID = textures[0];
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D,
                GL10.GL_TEXTURE_MAG_FILTER,
                GL10.GL_LINEAR);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                GL10.GL_CLAMP_TO_EDGE);

        gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
                GL10.GL_REPLACE);

        InputStream is = mContext.getResources()
                .openRawResource(R.raw.robot);
        Bitmap bitmap;
        try {
            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch(IOException e) {
                // Ignore.
            }
        }

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();
    }

GLの初期設定と、Textureの準備を行っている。
リソースのR.raw.robotをbitmapにして、それを
GLUtils.texImage2D()でTextureに設定している。
(ちなみに、R.raw.の中にリソースを配置するとDPI(画素密度)によらず、
常にオリジナルの画像を使用してくれるらしい)


onSurfaceChangedは画面サイズが変わった、たとえば回転などのときに呼ばれる。
画面サイズを設定したり、GLの再設定をしたりする。
初回にも上記onSurfaceCreated()の後に呼ばれてくる。
今回は、以下の処理を行っている。

    public void onSurfaceChanged(GL10 gl, int w, int h) {
        gl.glViewport(0, 0, w, h);

        float ratio = (float) w / h;
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);

    }

視点(Viewportと射影行列)に関する設定。
Viewportは画面の幅と高さ。Frustum(視錐台)で見える範囲を設定。
2Dの場合はPerspectiveをOrtho設定とする。遠くも近くも同じ大きさになる。


onDrawFrameが毎回呼ばれる処理。
ここで描画する。
今回は、以下の処理を行っている。

    public void onDrawFrame(GL10 gl) {
        gl.glDisable(GL10.GL_DITHER);
        gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
                GL10.GL_MODULATE);

        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

        GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        gl.glActiveTexture(GL10.GL_TEXTURE0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureID);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                GL10.GL_REPEAT);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                GL10.GL_REPEAT);

        long time = SystemClock.uptimeMillis() % 4000L;
        float angle = 0.090f * ((int) time);

        gl.glRotatef(angle, 0, 0, 1.0f);

        mTriangle.draw(gl);
    }

画面をクリアしてからモデルビュー行列に対して設定しています。
特にここでは、システムから時間を取得して回転角度を更新させています。
最後のdrawは以下のとおり。

    public void draw(GL10 gl) {
        gl.glFrontFace(GL10.GL_CCW);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, VERTS,
                GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
    }

頂点配列(mFVertexBuffer。事前に三角形の座標を格納している)と
それに対応するテクスチャ座標配列(mTexBuffer)を設定してDrawElementsで
描画しています。ここではドロイド君がテクスチャとして貼られた
三角形が表示されます。

これはGLES1.1の場合の処理です。
GLES2.0の場合はシェーダプログラムが必要になります。


onDraw()では描画のみで、画面の更新はしない。
画面の更新はEGLが行う。

GLSurfaceView.javaのなかにEGLHelperクラスがあり、その中に
swap()関数がある。

        public boolean swap() {
            if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {

                int error = mEgl.eglGetError();
                switch(error) {
                   ....
                }
            }
            return true;
        }

というわけで、ただ単にeglSwapBuffers()を呼び出しているだけです。

ApiDemosを調べる1 - 初期Activityの表示

  • ApiDemoApplication.javaのonCreate()を実行する。
  • ApiDemo.javaのonCreate()を実行する。
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Intent intent = getIntent();
        String path = intent.getStringExtra("com.example.android.apis.Path");
        
        if (path == null) {
            path = "";
        }

        setListAdapter(new SimpleAdapter(this, getData(path),
                android.R.layout.simple_list_item_1, new String[] { "title" },
                new int[] { android.R.id.text1 }));
        getListView().setTextFilterEnabled(true);
    }

ここではpathにnullが返ってくるので、path=""が実行される。
setListAdapter()を用いて、ListにAdapterを設定する。
ここではSimpleAdapter()を用いている。
解説はコンピュータクワガタさんへ

第2引数に、リストに列挙するデータを渡す。
第3引数は、リストの書式(xml)、第4引数はデータのキー、
第5引数にはキーに対する書式(xml)を記述する。

getDataの中身は以下のとおり。

    protected List getData(String prefix) {
        List<Map> myData = new ArrayList<Map>();

        Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
        mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);

        PackageManager pm = getPackageManager();
        List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);

        if (null == list)
            return myData;

        String[] prefixPath;
        
        if (prefix.equals("")) {
            prefixPath = null;
        } else {
            prefixPath = prefix.split("/");
        }
        
        int len = list.size();
        
        Map<String, Boolean> entries = new HashMap<String, Boolean>();

        for (int i = 0; i < len; i++) {
            ResolveInfo info = list.get(i);
            CharSequence labelSeq = info.loadLabel(pm);
            String label = labelSeq != null
                    ? labelSeq.toString()
                    : info.activityInfo.name;
            
            if (prefix.length() == 0 || label.startsWith(prefix)) {
                
                String[] labelPath = label.split("/");

                String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];

                if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
                    addItem(myData, nextLabel, activityIntent(
                            info.activityInfo.applicationInfo.packageName,
                            info.activityInfo.name));
                } else {
                    if (entries.get(nextLabel) == null) {
                        addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
                        entries.put(nextLabel, true);
                    }
                }
            }
        }

        Collections.sort(myData, sDisplayNameComparator);
        
        return myData;
    }
  • Intentを用いて、Activityを取得する。
  • Activityのパスを編集(app.Helloworldからappのみ取り出す)
  • myDataに名前とIntentを格納する(addItem()。この時Intentにprefix情報を付加しておく)

最後に、ここで設定したAdapterを設定する(setListAdapter())ことで、
List表示されるようになる。

Listをクリックすると、別なActivityが開く。
それを実装しているのが以下。

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Map map = (Map) l.getItemAtPosition(position);

        Intent intent = (Intent) map.get("intent");
        startActivity(intent);
    }
}
  • クリックすると、onListItemClick()に飛んでくる(コールバック関数)
  • ListViewの中のデータを取得するためにはgetListView().getItemAtPosition(position)する
  • ここでは、先に設定したIntentを取得する。
  • intentで指定されたActivityへ遷移する

→apisをクリックすると以下のIntentが選択される

  1. packageName=com.example.android.apis.ApiDemos
  2. className=com.example.android.apis

つまり、またこのActivityのonCreateに遷移する。

2回目に呼び出された場合、onCreateの

        String path = intent.getStringExtra("com.example.android.apis.Path");

の部分にpathが入力される。ここにはクリックされたアイテム
の名前が入る。

2回目のonCreateではそのクリックされたアイテム以下の
階層にのみアクセスして、ListViewに表示する。

ここで、改めてAndroidManifest.xmlの一部を見てみると、

                android:label="Graphics/OpenGL ES/Frame Buffer Object"
                android:label="Graphics/OpenGL ES/Cube Map"

といったlabelがある。

最初にGraphicsをクリックするとGraphics以下のものがListとして表示され、
OpenGL ESをクリックすると、それ以下のもの(たとえばFrame Buffer Object)
表示される。

最後に、Frame Buffer Objectをクリックすると、該当のActivityに
アクセスできるIntentを取得して、startActivityする、

という流れのようです。

個別のActivityについては省略。

画面遷移とIntent

Intent(Androidのド肝)

これを参考にメモがき。

  • AndroidManifest.xmlにアプリ内で使用するActivityをすべて記述する。
  • android.intent.action.MAINと書かれているActivityがエントリポイント

  ・・・複数ある場合もあるのですが???

  • intentを用いて、画面遷移可能。
Intent intent = getIntent();    // deprecated(非推奨)
intent.setClassName(pkgName, className);
startActivity(intent);
  • 遷移先から値を取得したい場合はstartActivityForResult()を使用する。

Android SDK Managerでfetchに失敗する

以前はSDK and ADT Managerという形で統合されていたSDK Managerですが、
分離されています。

このSDK Managerを使ってWebから様々なPlatformやToolをダウンロード
出来るはずですが、

Failed to fetch URL https://dl-ssl.google.com/android/repository/repository.xml

などと表示されてしまい、ダウンロードできないことがあったので、メモ。
ちなみに、
http://developer.android.com/sdk/installing.html
ここの"Step.3 Installing the ADT Plugin for Eclipse"までは終了しているものとする。

対策法1:httpsをhttpにしてみる。

ホームディレクトリ、すなわち、

"C:\Documents and Settings\ユーザー名"

以下に、".android\androidtool.cfg"を作成して、以下のように記述する。

sdkman.force.http=true

→これで駄目だったので、次へ。

対策法2:proxy設定

Eclipseの[Window]-[Preferences]-[General]-[Network Connections]で
設定を行う。特にHTTP, HTTPSの設定が必要。


→これで駄目だったので、次へ。
 (本来は正しく設定できていれば取得できると思うが、設定がよくわからなかった)


対策法3:直接DLする

Android SDK ライブラリ強制インストール
を参考に、直接ダウンロードを試みました。これがうまくいきました。

配置場所

Windowsの場合、DL(後述)したファイルを
"C:\Program Files\Android\android-sdk"以下に配置すれば
良いらしいです。具体的には以下の通り。

android-sdk\add-ons
 - google APIを格納します。
 - addon_google_apis_google_inc_15といったフォルダが格納されます()
 - add-onに対応したPlatformが無い場合、"Unable to find base platform with API level 'xx'"といったメッセージが出ます。

android-sdk\platforms
 - SDK Platformを格納します。開発に必須です。各種Versionに応じて取得します。
 - android-2.3.3_r01-linuxをrenameしたandroid-10といったフォルダが格納されます。
 - 以前のPlatformはWindows/Mac/Linuxで別ファイルだったようですが、今は統合されてすべてLinux命名されているようです。

android-sdk\platform-tools
 - Platformのツール。
 - これが無いと、Eclipse起動時に、adb.exeが無い、と怒られます。

android-sdk\extras\google\usb_driver
 - USB Driverを格納します(Windowsのみ)
 - extrasフォルダ以下はないので、作成します。

DLリンク

先ほどの、
Android SDK ライブラリ強制インストール
および
Android SDK リンクジェネレーター
に書かれています。

書かれていないものもあるので、以下のようにして探す。

その1:platform-tool


その2:add-onsおよびusb driver


その3:platform


参考:

platform -> android-sdk\platforms以下に格納する

http://dl-ssl.google.com/android/repository/android-2.2_r03-linux.zip
http://dl-ssl.google.com/android/repository/android-2.3.1_r02-linux.zip
http://dl-ssl.google.com/android/repository/android-2.3.3_r02-linux.zip
http://dl-ssl.google.com/android/repository/android-3.0_r02-linux.zip
http://dl-ssl.google.com/android/repository/android-3.1_r03-linux.zip
http://dl-ssl.google.com/android/repository/android-3.2_r01-linux.zip
http://dl-ssl.google.com/android/repository/android-14_r03.zip
http://dl-ssl.google.com/android/repository/android-15_r02.zip

samples -> android-sdk\platforms\android-xxx以下にsamplesフォルダを作って格納する

http://dl-ssl.google.com/android/repository/samples-2.2_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-2.3_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-2.3.3_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-3.0_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-3.1_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-3.2_r01-linux.zip
http://dl-ssl.google.com/android/repository/samples-14_r02.zip
http://dl-ssl.google.com/android/repository/samples-15_r01.zip

tools
http://dl-ssl.google.com/android/repository/tools_r16-windows.zip
http://dl-ssl.google.com/android/repository/tools_r16-linux.zip
http://dl-ssl.google.com/android/repository/tools_r16-macosx.zip

docs
http://dl-ssl.google.com/android/repository/docs-15_r01.zip


usb driver
http://dl-ssl.google.com/android/repository/usb_driver_r04-windows.zip

Buttonにイベントをつける

Button(またはImageButton)がクリックされた時にこうしたい・・・
という処理を記述する方法。

        Button myButton = (Button)findViewById(R.id.myBtn);	// IdからButtonを取得。ImageButtonならImageButtonクラスで取得。

        myButton.setOnTouchListener(new Button.OnTouchListener() {	// タッチされた時に受ける関数を設定
        	
        	@Override
        	public boolean onTouch(View v, MotionEvent event){
        		int action = event.getAction();
        		switch(action){
        		case MotionEvent.ACTION_DOWN:{		// ボタンに触った時にここに来る
        			myDownFunc();
        			return true;
        		}
        		case MotionEvent.ACTION_UP:{		// 指がボタンから離れたらここに来る
        			myUpFunc();
        			return true;
        		}
        		}
        		return false;
        	}
        });

ところで、OnTouchListener以外に、OnClickListenerもあるので、気になって調べた。

Viewのクリックイベント - ソフトウェア雑記 さま

これによれば、OnTouchListenerは触れたと離れたそれぞれに対してイベントが来るらしい。
OnClickListenerはクリック、すなわち触れたと離れたのワンセットでイベントが来るらしい。

このほか、長押しの場合にはOnLongClickListenerというリスナーからもイベントが来るらしい。

  • 触れた
  • 長押し(長押しの場合のみ)
  • 離れた
  • クリック

の順番でイベントが来るらしい。ちなみに、長押しではコールバック関数として
OnLongTouch(View v)を用いるそうです。クリックはOnClick(View v)。

その他、trueを返すとそれ以降のイベントが飛ばないらしいです。
長押しで処理したら後はイベントいらない、、、ということでしょうか。

長押しに対応している辺りが助かりますね。
Windowsはそういうの無い(?)ですから、自分で何とかするしかないです。
組み込みのことを考慮したOSなんだなぁと感心しました。


Androidをあわてて勉強してる身分ですが、
本当に勉強になります。見知らぬ方、ありがとうございます。

ImageButtonのボタンを透過する

探していたら、そのもののページがあった。

ImageButtonを透過にする(GENDOSUさま)

要するに、

android:background="@null"

をImageButtonの要素に追加すればよいとのこと。

GUIから出来ないのですが、Androidってこんなもんですか!

ちなみに

android:background="#00000000"

とかやって、直色指定でも出来るらしい。エミュレータで試したら。aarrggbbの順番でした。(ABGRではない)
左2桁がアルファ(透過率というけど、正確には不透過率)。
00000000だと完全透過。80000000だと半透過。