Hatena::Groupandroid

lnzntの Android 日記 このページをアンテナに追加 RSSフィード

2012年04月16日(月)

MIT App Inventor を使ってみた

23:11 | MIT App Inventor を使ってみた - lnzntの Android 日記 を含むブックマーク はてなブックマーク - MIT App Inventor を使ってみた - lnzntの Android 日記 MIT App Inventor を使ってみた - lnzntの Android 日記 のブックマークコメント

MIT App Inventor を使ってみました。

現在は、Google Labs(閉鎖した?) から MIT に移管されているようです。

上記ページの右側に入り口のボタンがあります。

f:id:lnznt:20120416230225j:image

Google アカウントで認証されます。

なので ログインには Google アカウント(と初回には認証の許可)が必要です。

----

ログインすると以下のような画面を開けます。

エディタ画面

20120416230848

プロジェクト管理の画面

20120416230847

ブロックエディタ画面 (これをいじってみたかった)

20120416230849

----

ブロックエディタは JPNL です。Java Web Start で開始します。

私の Ubuntu Linux 環境の話ですが、Firefox では、ブロックエディタ自身は起動しても、ブラウザとコネクトできず編集中のオブジェクトが読み込めません。(なぜ??)

なので、MIT へのアクセスは Google Chrome を使用してます。

JPNL は一旦ダウンロードしてからコマンドラインで起動してます。

$ javaws AppInventorForAndroidCodeblocks.jnlp  # ブロックエディタが起動する

----

(今、思い出しました。。)最初ブロックエディタの起動時に、"Commands for AppInventor" がインストールされてないという警告ダイアログがでます。私は、以下のページにリンクされている deb パッケージからインストールしました。

セットアップについては以下のページに書かれています。

----

アプリは、(実機がないので)パッケージをダウンロードしてからエミュレータで実行してます。

f:id:lnznt:20120416230852j:image

# エミュレータを起動してから adb でアプリをインストールする
$ adb install Hello.apk

----

以下の動画を見て、見様見真似でアプリを作りました。

ボタンを押すと画像が表示されて音が鳴るアプリです。(Eclipse 管理の AVD で実行)

f:id:lnznt:20120416230850j:image

f:id:lnznt:20120416230851j:image

簡単に作れました。(前回同様、音が鳴らないのは悩みましたが)

MediaPlayer

23:00 | MediaPlayer - lnzntの Android 日記 を含むブックマーク はてなブックマーク - MediaPlayer - lnzntの Android 日記 MediaPlayer - lnzntの Android 日記 のブックマークコメント

MediaPlayer を使うサンプルを書いてみました。

f:id:lnznt:20120416224349j:image

エミュレータで音が再生されない

エミュレータで音が再生されないことがあります。

Snapshot を使わずに、UserData を wipe して起動しなおすと再生できます。

ググるとよく出てくる -useaudio オプションは既にないようです。

実装

public class MediaPlayerSampleActivity extends Activity
{
    private static final String TAG = "MediaPlayerSample";
    private MediaPlayer mediaPlayer = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        mediaPlayer = MediaPlayer.create(this, R.raw.sample);
    }

    @Override
    protected void onDestroy() {
	super.onDestroy();
			
	mediaPlayer.release();
	mediaPlayer = null;
    }

    /*
       MediaPlayer の状態にマッチしない API をコールするとエラーになる
    */
    public void onStartPlayer(View v) {
	if (! mediaPlayer.isPlaying()) {
		mediaPlayer.start();
		Log.d(TAG, "player start.");
	}
    }
	
    public void onStopPlayer(View v) {
	if (mediaPlayer.isPlaying()) {
		mediaPlayer.stop();
		Log.d(TAG, "player stop.");
		
		try {
			mediaPlayer.prepare();
		} catch (IOException e) {
			mediaPlayer.release();
			mediaPlayer = null;
		}			
	}
    }
}

音声ファイルは res/raw/sample.ogg (適当に用意)。

res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/start_label" android:onClick="onStartPlayer"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/stop_label" android:onClick="onStopPlayer"/>

</LinearLayout>

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MediaPlayerSample</string>
    <string name="start_label">Start</string>
    <string name="stop_label">Stop</string>

</resources>

アラーム

22:48 | アラーム - lnzntの Android 日記 を含むブックマーク はてなブックマーク - アラーム - lnzntの Android 日記 アラーム - lnzntの Android 日記 のブックマークコメント

アラームを使うサンプルを書いてみました。

ボタン押すと30秒後のアラームをセットして、別のアクティビティを起動します。

f:id:lnznt:20120416223824j:image

f:id:lnznt:20120416223825j:image

f:id:lnznt:20120416223826j:image

実装

src/.../AlarmSampleActivity

public class AlarmSampleActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    
    public void onClick(View v) {
    	AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    	
    	Intent intent = new Intent(this, SubActivity.class);
    	PendingIntent sender = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
       	long atTime = System.currentTimeMillis() + (30 * 1000);
 
       	alarm.set(AlarmManager.RTC, atTime, sender);
       	Log.d("AlarmSample", "set alarm");
       	
       	TextView text = (TextView)findViewById(R.id.message);
       	text.setText(getString(R.string.waiting_message));
    }
}

src/.../SubActivity.java

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

res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/message"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/message" />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/button1_label" android:onClick="onClick"/>
</LinearLayout>

res/layout/sub.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />
</LinearLayout>

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">AlarmSample</string>
    <string name="message">ボタンを押してください。</string>
    <string name="button1_label">Alarm Set</string>
    <string name="hello">Hello!</string>
    <string name="waiting_message">30秒後に SubActivity が起動します</string>
</resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarmsample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".AlarmSampleActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:label="@string/app_name" android:name="SubActivity"></activity>
    </application>
</manifest>

最初、マニフェストに SubActivity を登録するのを忘れてて、LogCat にエラーも出てないのに SubActivity が起動せず、少し悩みました。

Google Map API

01:07 | Google Map API - lnzntの Android 日記 を含むブックマーク はてなブックマーク - Google Map API - lnzntの Android 日記 Google Map API - lnzntの Android 日記 のブックマークコメント

Google Map API 使ってみました。

f:id:lnznt:20120416010952j:image

Google Map API キー

Google Map にアクセスするのに Google Map API キーが必要です。

Google Map API キーの取得には以下が必要です。

  • 証明書
  • Google アカウント

デバッグ用の証明書は SDK に添付されてます。

keytool で内容表示できます。

$ keytool -list -keystore ~/.android/debug.keystore 
キーストアのパスワードを入力してください:   (ここは「空Enter」でよい)

*****************  警告 警告 警告  *****************
*  キーストアに保存された情報の完全性は検証されて  *
*  いません!  完全性を検証するには、キーストアの   *
*  パスワードを入力する必要があります。            *
*****************  警告 警告 警告  *****************

キーストアのタイプ: JKS
キーストアのプロバイダ: SUN

キーストアには 1 エントリが含まれます。

androiddebugkey, 2012/04/11, PrivateKeyEntry, 
証明書のフィンガープリント (MD5): XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX

最下行に証明書のフィンガープリントが表示されます。(API キー取得時に使います)

Google Map API キーの取得

以下のページのフォームから Google Map API キーが取得できます。

画面に従って取得します。

手続きの中で、証明書のフィンガープリントの入力が求められます。

また、Google アカウントの認証も求められます。

http://code.google.com/intl/ja/android/maps-api-signup.html

アプリを配布するには、デバッグ用でない証明書で、Map API キーを取得する必要があるそうです。

実装

ターゲットは「Android x.x.x」でなく「Google APIs」になります。

以下の時に注意します。

  • プロジェクト作成
  • AVD 作成

以下、ソースコードです。

----

src/.../GoogleMapSample

package com.example.googlemapsample;

import android.os.Bundle;
import com.google.android.maps.MapActivity;  // import する

public class GoogleMapSampleActivity extends MapActivity { // 基底クラスは MapActivity
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    protected boolean isRouteDisplayed() {  // オーバーライドが必要
	return false;
    }   
}

res/layout/main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- 以下の MapView を追加する。android:clickable はオプション -->
    <com.google.android.maps.MapView
                 android:layout_width="fill_parent"
                 android:layout_height="fill_parent"
                 android:clickable="true"
                 android:apiKey="(ここに、Google Map API キーを入れる)"
                 />
</LinearLayout>

res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">GoogleMapSample</string>
</resources>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.googlemapsample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="15" />
    <uses-permission android:name="android.permission.INTERNET"/> <!-- 追加 -->

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".GoogleMapSampleActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <uses-library android:name="com.google.android.maps"></uses-library> <!-- 追加 -->
    </application>
</manifest>