2012年5月8日火曜日

AlertDialogの使い方(基本)



■AlertDialog

AlertDialogは、コンストラクタがprivateになっており 直接 new 出来ないので注意!
AlertDialog.Builder経由で、new してやる必要がある

●通常のダイアログ表示
// ダイアログの表示
AlertDialog.Builder dlg = new AlertDialog.Builder(this);
dlg.setTitle("TEST");
dlg.setMessage("Hello, World!");
dlg.show();

●選択ダイアログの表示
AlertDialog.Builder dlg = new AlertDialog.Builder(this);
dlg.setIcon(R.drawable.icon);
dlg.setTitle("Select Dialog");
dlg.setMessage("選択してください");
dlg.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
        /* YES 選択時の処理 */
    }
});
dlg.setNegativeButton("No", new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int whichButton) {
       /* NO 選択時の処理 */
   }
});
dlg.show();

他にも、リストや複数の選択肢、プログレスバーなどを扱うことができる

■参考アドレス
http://www.hakkaku.net/articles/20090924-581
http://wikiwiki.jp/android/?UI%A

2012年5月7日月曜日

android ファイル操作の種類



通常のファイル格納領域
アクセス許可さえあれば、javaのファイルアクセスAPIを用いてアクセス可能
例)Fileクラスのdelete()など

※注 sdcard へのアクセスはマニフェストにパーミッションの追記が必要
(パスは、/sdcard, /mnt/sdcard/など。端末依存?)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
★sdcardだけでなく、内蔵diskへのアクセスも↑が必要だった★

■アプリケーション配下のファイル格納領域
android側で独自に定義されたAPIを用いる
openFileOutput(ファイル名, モード)/openFileInput(ファイル名)/deleteFile(ファイル名)

・「data」デレクトリ
/data/data/パッケージ名/files
アプリケーション専用のデータ領域
/data/data/パッケージ名/database
データベース
/data/data/パッケージ名/shared_pref
Preferenceを格納

・「assets」デレクトリ
読み込み専用
assetsディレクトリを作成して保管したファイルを読み込む事が可能
ResourcesクラスのopenRawResource(R.raw.ファイル名)や
例)AssetManager.oepn(ファイル名)など

・「raw」デレクトリ
読み込み専用
リソースIDを指定してのファイル読み込みが可能
例)getString(リソースID)や、ResourcesクラスのgetString(リソースID)など

■参考

2012年3月19日月曜日

Notificationのフラグによる動作の設定


Notificationクラスのflagフィールドに代入することで、下記設定が可能
フラグは OR で代入して、複数設定することも出来る。

Notification.FLAG_AUTO_CANCEL
 しばらくすると自動的に通知が消える。ポップアップでお知らせするために使える

Notification.FLAG_INSISTENT
 通知ウィンドウを開くか、キャンセルされるまで、音が鳴り続ける。かなりうざそう

Notification.FLAG_ONGOING_EVENT
 通常の通知ウィンドウの上位のバーの部分に表示する。常に常駐するアプリに使える。

Notification.FLAG_NO_CLEAR
 通知をクリアを押してもクリアできないようにする FLAG_ACTIVITY_NEW_TASK ?

2012年2月20日月曜日

Preferenceの使い方 2

preferences.xmlを使わずに直接書き込みを行う方法

 
     SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
     Editor e = pref.edit();
     e.putString("ip", "保存するテキスト");
     e.putString("path",  "保存するテキスト" );
     e.commit();
こんな感じ。

2012年2月9日木曜日

PendingIntent

RemoteViewやNotificationクラスに用いるPendingIntentというもの
よく理解出来ていないため少し整理してみます。

これはタイミングを指定して発行することができるIntentのようです。
new したIntentを、直ちに発行するのではなく、ボタンを押されたタイミングで発行する等に
利用するようです。
引数でIntentのインスタンスを受けとって包むので、Wrapper的な役割ですかね。

PendingIntentは、以下のstatic メソッドから取得できる
どこに対して発行するかによって、作り方が違う

getActivity(Context, int, Intent, int)
→Activityへ投げる
getBroadcast(Context, int, Intent, int)
→ブロードキャストへ投げる
getService(Context, int, Intent, int);
→Serviceへ投げる

例えば、Notificationに使う場合は、
通知バーをタップしたタイミングでIntentが発行されるという感じのようです。

PendingIntent自身はOSが管理しているものなので
PendingIntentを起動した元のActivityが死んでも、それはOSによって残り続け
通知バーをタップしたタイミングで、Intentが投げられ、
元のAcitivyが起動されるという感じのようです(自信なし)

■参考にさせて頂いたサイト:
http://y-anz-m.blogspot.com/2011/07/androidappwidget-pendingintent-putextra.html

2012年2月6日月曜日

ProgressBarの使い方


プログレスバー(進捗)の表示には、ProgressBarウィジェットを用いる。

スタイルの指定(XMLレイアウト)
android:progressBarStyle        通常の円
android:progressBarStyleHorizontal   水平方向のバー
android:progressBarStyleLarge      大きい円
android:progressBarStyleSmall      小さい円

StyleHorizontal 使用時に限り、進捗状況の表示が可能になる。

メソッド:
setMax() プログレスバーの最大値の指定。上限はint型の範囲。
setProgress() 現在の進捗の値を設定(濃い色で表示される)
setSecondaryProgress() セカンダリの値の指定(薄い色で表示される)

使用例)
ProgressBar progress = (ProgressBar) findViewById(プログレスバーWidgetのID);
progress.setMax(100);
progress.setProgress(20);
progress.setSecondaryProgress(70);

2012年1月31日火曜日

RemoteViewsの使い方

別プロセス上で表示可能となる階層的なViewを記述するクラス
Viewは、レイアウトリソースファイルを指定してインフレートする。

// 生成
RemoteViews view = new RemoteViews(パッケージ名, レイアウトID)

// 以下の用に、指定したVIEWに対してリソースをセットする
view.setImageViewResource(VIEW_ID, リソースID);
view.setTextViewText(VIEW_ID, "text data");
view.setProgressBar(VIEW_ID, 100, progress, false);

// またPendingIntentをセットして、ViewからIntent発行をしたり出来るらしい★未検証
.setOnClickPendingIntent(VIEW_ID, pendingIntent);

このRemoteViews を用いて、Notificationクラスの、contentViewにセットすることで
独自のレイアウトをNotificationに表示させることが出来るようです。

AIDLによる Service ⇔ Activity間通信


●AIDLとは?
→android上でプロセス間通信を行うためのもの
 Service側に実装されたコールバック用のインターフェースを
 Activityが受け取ることで、Serviceの処理を呼び出すことが可能
 逆に ServiceからActivityのメソッドも呼び出せるらしい? ★ 要調査
 最初のテンプレートさえ覚えておけば、使い方は特に問題なさそう

1.AIDLファイルの作成
拡張子 .aidl のファイルを作成し、その中に下記のようにインターフェースを書く
javaソースと同じフォルダに置く

 
interface IServiceMethod
{
void CallServiceMethod();
}

2.サービスの実装

class MyService extends Service implements IServiceMethod
{
    @Override
    public IBinder onBind(Intent intent) {
        if(IServiceMethod.class.getName().equals(intent.getAction())){
            // IServiceMethodのインスタンスを返す
            return isvc;
        }
        return null;
    }

private IServiceMethod.Stub isvc = new IServiceMethod.Stub()
{
public void CallServiceMethod() throws RemoteException {
// Service側で実行する処理を実装
}
};
}

ビルドすると gen フォルダに自動生成された IServiceMethod.javaが出来る。
中身を見ると、Stub という名前の内部抽象クラスがあり、.aidl ファイルで宣言したメソッドが定義される。
このインターフェースを実装した Stabクラスのインスタンスを bind時に返せばOK。


3.Activityの実装
 
public class IPCMain extends Activity {

IServiceMethod aidl = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // MyServiceにbindする
        Intent i = new Intent(this, android.study.kai.MyService.class);
        bindService(i, serviceConnection, BIND_AUTO_CREATE);
    }

    @Override
    public void onDestroy()
    {
    super.onDestroy();
    // MyServiceからアンバイド
    unbindService(serviceConnection);
    }

    private ServiceConnection serviceConnection = new ServiceConnection()
    {
    // サービスとの接続時に呼ばれる
        public void onServiceConnected(ComponentName name, IBinder ibinder)
        {
        // Ibinder インターフェースから、AIDLのインターフェースにキャストするメソッドらしい
        aidl = IServiceMethod.Stub.asInterface(ibinder);
        }

    // サービスとの切断時に呼ばれる
        public void onServiceDisconnected(ComponentName name)
        {
        aidl = null;
        }
    };
}

bindServiceと、unbindServiceを呼び出し、サービスと接続/切断する
Serviceのインターフェースは、bind成功時に呼ばれる
インターフェースから取得できる

●bindService
bindService(i, serviceConnection, BIND_AUTO_CREATE);

引数1: インデント。サービスのクラスを指定する?
引数2: ServiceConnectionの実装を指定する
    ServiceConnectionは、サービス接続、切断時に呼ばれる
    コールバック用のインターフェースである。
    接続時に、onBindで返したサービス側のインターフェースを取得できる
引数3: BIND_AUTO_CREATEを指定することでServiceが未起動の時に起動される

●unbindService
unbindService(serviceConnection);
引数1:ServiceConnectionの実装を指定する

2012年1月29日日曜日

Serviceの開始、停止

Activityからのサービスの開始と停止の指示。

 

// サービスを開始する
Intent i = new Intent(this, android2.study.yohei.MyService.class);
startService(i);

// サービスの停止する
Intent i = new Intent(this, android2.study.yohei.MyService.class);
stopService(i);
インテントを生成して、それを引数に起動するだけなので 意外とシンプルです。

Intentでの値の受け渡し方


Intentクラスに、値を受け渡すためのメソッドが用意されているので
これを用います。

★Set
 
i.putExtra("tag1", mConfig.mIpAddress);
i.putExtra("tag2", mConfig.mPortNum);
i.putExtra("tag3", mConfig.10080);

★Get
 
Intent i = this.getIntent();
boolean enable = i.getBooleanExtra("tag1", false);
String ipAddress = i.getStringExtra("tag2");
int portNum = i.getIntExtra("tag3", 10080);
上記の他にもいろいろあります。 ※Serviceの場合は、getIntent()がないのですが、onStartメソッドの引数で取得できます。

Notification

1.NotificationManager を取得する
 
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
2.Notificationオブジェクト生成
 
Notification notification = new Notification(
android.R.drawable.btn_default,
"通知情報が届きました",
System.currentTimeMillis());

・Notificationクラス
→通知情報のコンテキスト
 サウンド、バイブレーション、LEDを用いてアラートする事も
 引数1 icon 一覧に表示するアイコンID
 引数2 text 表示するテキスト
 引数3 表示する時間

3, PendingIntentを用意
 
Intent intent = new Intent(Intent.ACTION_VIEW);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
・PendingIntent
Intentを、タイミングを指定して発行することができるIntent。
時間を指定したり、イベント発生時に発行する。

4.通知情報の設定
 
notification.setLatestEventInfo(
getApplicationContext(),
"アプリ名",
"通知情報の説明文",
contentIntent);

5.一旦、Notificationを削除
 
nm.cancel(id)
6.Manager経由でNotify発行
 
nm.notify(R.string.app_name, notification);

Failed to install ----.apk on device

USBデバッグでデバイスを繋いだ状態で、apkをインストール出来なかった
症状が発生したのでメモ。

ググったところMP3をパッケージに含めたために
発生した転送のタイムアウトエラーでした。

「ウィンドウ」→「設定」→「Android」→「DDMS」→「ADB 接続タイム・アウト」
の時間を変更することで、問題解決。

2011年12月27日火曜日

謎のエラーで実行できない(2)


またしても、プロジェクトをビルドしても実行できなくなった。
ちょいとManifest.xmlをいじっていたり、使ってないプロジェクトを閉じたり
していただけなんだけど・・以下のエラーが出る。

> Error generating final archive: Debug certificate expired on ...

解決手順:

1.プロジェクト→クリーンを行う

↓それでも治らない

2.デバッグのキーストアとかゆう情報の期限切れらしい
JDKに付属する keytool というもので、キーストアを再度生成して置き換える
ことで問題は解決した。

●手順 A.キーストアの場所を確認
 →eclipseの「ウィンドウ」「設定」「Android」「ビルド」「Default debug keystore」から
パスを確認

自宅環境では以下の場所だった。
> C:\Documents and Settings\PCのユーザー名\.android\debug.keystore

●手順 B. keytool.exeを用いて、以下のコマンドでキーストアを生成する
keytoolがない場合はJDKをインストールする。
keytoolのパスが通っていない場合は、環境変数にパスを通して置く
自宅環境では以下の場所だった。
> C:\Program Files\Java\jdk1.6.0_23\bin

コマンドプロンプトで以下を実行

keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -validity 10000 -dname "CN=Android Debug,O=Android,C=US"

パスワードを要求されるので android と入力する

●手順 C.ファイルの置き換え
C:\Documents and Settings\PCのユーザ名\.android

に debug.keystore というファイルが出来ていたので
それを、Aのファイルに置き換える。

●手順 D.
実機を繋いでいる場合は、一度apkをアンインストールしてから
もう一度、プロジェクトをCleanして実行する


参考サイト
http://magpad.jugem.jp/?eid=151
http://magpad.jugem.jp/?eid=77

2011年12月19日月曜日

ステータスバーに進捗を表示する


1.OnCreate()と、SetContentView()の間にプログレスバーの許可を書く

// プログレスバー許可
requestWindowFeature(Window.FEATURE_PROGRESS);


2. SetContentView()後に、まずはプログレスバーをOFFにしておく

// プログレスバー表示の設定
setProgressBarVisibility(false);

3.以下のメソッドで、プログレスバーを操作

引数は、 0 - 10000 の範囲で進捗を通知する。
10000になるとプログレスバーが消える

setProgress();

以上!

2011年12月18日日曜日

オプションメニューの作り方


使い方は、Activityのメソッドをオーバーライドする方式なので簡単。

○説明
menu.addメソッドでメニューを追加する。
・2番目の引数のMENU_ID01にメニューIDを指定する。Menu.FIRSTから順番に指定していけばOK
・4番目の引数に、メニュー名を指定する 
 
@Override
// オプションメニュー生成時のイベント
public boolean onCreateOptionsMenu(Menu menu)
{
 // オプションメニューを生成、追加する
 MenuItem item = menu.add(Menu.NONE, MENU_ID01, Menu.NONE, "SampleMenu");
 // アイコンを設定する
 // android.R.drawable内にシステムデフォルトのアイコンが多数用意されている
 item.setIcon(android.R.drawable.ic_menu_preferences);
 // キーボードショートカット
 item.setAlphabeticShortcut('e');
 return super.onCreateOptionsMenu(menu);
}

@Override
// オプションアイテムクリック時のイベント
public boolean onOptionsItemSelected(MenuItem item)
{
 switch (item.getItemId())
    {
    case MENU_ID01:
     // メニューが選択されたときの処理
     break;
    default:
        break;
    }
    return super.onOptionsItemSelected(item);
}

@Override
// オプションメニューが閉じられたときのイベント
public void onOptionsMenuClosed(Menu menu)
{
}

2011年12月5日月曜日

実行時にeclipseのコンソールに謎のエラー


ファイルダイアログを作りたかったが
難しそうだったので、フリーの外部ソースをパクって来て
埋め込んだら、突然、以下のエラーが出て起動すらしなくなった。

ERROR: Unknown option '--no-crunch' ~

最初は、コードのバグを疑ったがようやらそうではなかった。
ググッてみたところ、SDK Managerのアップデートしたら解決した。
eclipseのアップデートからだけではダメなようで
SDK Managerを起動して、そこからキチンとupdateしましょう。

いままでのソケット通信をするアプリは、このバージョンで問題なく動いてたのだけど
何からの処理に依存して、上記のエラーが発生するのだろうか・・。

2011年8月30日火曜日

Java言語の不満

以下のように、インターフェースの実装を簡略化して書けるのだが
どうも無理やり押し込んだ感のある文法が好きになれない。
この場合、ローカル変数 localnum を
感覚的に参照出来るそうに見えるが、実際はできない。

その点、C#は、デリゲートやアクセッサがいい役割を果たしていて
かなり感覚的に読みやすいコードが書けるのでオススメだ。

public class Main implements InterfaceA
{
 private int classnum = 10;

 public void Test()
 {
  // パッと見でローカル変数も送れそうな感じがするが送れない
  int localnum = 10;

  // その場でインターフェースを実装
  ClassA a = new ClassA( new InterfaceA()
  {
   // 実装2
   @Override
   public void play()
   {
    //System.out.println("実装1, num=" + localnum); // 当然ローカル変数は NG
    System.out.println("実装1, num=" + classnum);
   }
  });

  a.play(); //  実装1がよばれる

  // 通常
  ClassA b = new ClassA();
  b.setInterfaceA(this);
  b.play(); //  実装2がよばれる
 }

 @Override
 public void play()
 {
  System.out.println("実装2, num=" + classnum);
 }
}
※補足 最近知ったのですが、C# 2.0 では匿名メソッドという機能が用意されていて 上記と似たようなかたちで、delegateに直接関数を実装できるようです。

2011年7月28日木曜日

AppWidgetの作成方法

Androidのホーム画面に貼りつけできるAppWidgetの作り方

1.レイアウト画面の作成
通常アプリ同様 layout/xml 以下にレイアウトを作成する

2. res/xmlフォルダに、appwidget-provider設定ファイルの作成

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:minWidth="72dip"
  android:minHeight="72dip"
  android:updatePeriodMillis="60000"
  android:initialLayout="@layout/レイアウトのXMLファイル(.xmlは不要)"
/>

○サイズ指定(単位はdip)
・n dip = 74 x n - 2
・nはブロック数。nは1~4まで

・更新間隔(android:updatePeriodMillis)
・30分以下は30分として扱われる
・ミリ秒間隔で、onUpdate()が呼ばれる
・バッググラウンドでも更新が発生する
・0を指定すると、onUpdate()メソッドは一度だけ呼ばれる。
onUpdeteで呼ばれると、インスタンスが再生成されることに注意。
パラメータは、static にすれば保持できる

3.AndroidManifest.xmlの編集

<receiver android:name="クラス名" android:label="アプリ名">
  <intent-filter>
    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
  </intent-filter>
  <meta-data android:name="android.appwidget.provider" android:resource="@xml/設定用XMLファイル(.xmlは不要)" />
</receiver>

4.コードを記述
AppWidgetProvider を継承したクラスを作成する


public class WordsWidgets extends AppWidgetProvider {

 @Override
 public void onEnabled(Context context) {
  super.onEnabled(context);
 }

 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  super.onUpdate(context, appWidgetManager, appWidgetIds);
 }

 @Override
 public void onDeleted(Context context, int[] appWidgetIds) {
  super.onDeleted(context, appWidgetIds);
 }

 @Override
 public void onDisabled(Context context) {
  super.onDisabled(context);
 }

 @Override
 public void onReceive(Context context, Intent intent) {
  super.onReceive(context, intent);
 }
}

2011年7月21日木曜日

レイアウトのまとめ


●レイアウトの指定

◆LinearLayout
縦または横の一列に並べるレイアウト
android:orientation="vertical"か"horizontal"を
指定することで、縦か横かを指定する

○android:orientation
・vertical/horizontal
LinearLayoutを指定したとき設定する
それぞれ縦、横一列に並べることができる

◆RelativeLayout
ヴューの位置を、相対的な位置で指定する
android:gravity属性を指定して、相対的な位置を指定すること


○他のヴィジェットを基準にして、位置を決めるプロパティ
・android:layout_above=”@id/XXXX″
・android:layout_below=”@id/XXXX″
・android:layout_toLeftOf=”@id/XXXX″
・android:layout_toRightOf=”@id/XXXX″
指定されたヴィジェットに対して(上/下/左/右)の場所に配置する

・android:layout_alignTop=”@id/XXXX″
・android:layout_alignBottom =”@id/XXXX″
・android:layout_alignLeft=”@id/XXXX″
・android:layout_alignRight=”@id/XXXX″
指定されたヴィジェットから(上/下/左/右)に整列させる

・android:layout_alignBaseLine=”@id/XXXX″
2つのヴィジェットのベースラインを揃える

●レイアウトパラメータ

◆android:layout_height/android:layout_width

・fill_parent
元のビューのサイズに関係なく可能な限り拡大する
ビューの幅や高さを設定しても無効となる

・match_parent
fill_parentと同じ。 API レベル8以降だと fill_parentではなく
match_parentとする

・wrap_content
表示に必要なサイズに設定する
「setWidth」メソッドや「setHeight」メソッドで
ビューに幅と高さを設定していた場合には、その設定されたサイズに調整される

◆android:gravity
オブジェクトの配置方法を指定する
"|"で区切り複数指定することも出来る

・top/bottom/left/right
上下左右に配置する
・fill_vertical/fill_horizontal
高さ/幅を、コンテナのサイズに合わせる
・fill(default)
高さと幅を、コンテナのサイズに合わせます。
・center_vertical/center_horizontal/center
左右中央/上下中央/上下左右中央に配置し、サイズ変更は行わない

2011年7月18日月曜日

Preferenceの使い方

androidでは、アプリケーションなどの設定情報はXMLファイルとして保存される。
これを簡単に読み書きできる方法がある。

やり方:
1. res/xml 配下に、preferences.xmlを追加する
2. ルートタグ preferencescreen とした、設定用のXMLファイルを記述する
3. PreferenceActivityを継承した、Preference専用のアクティビティを作り
 addPreferencesFromResource()で、先ほど追加したXmlファイルのリソースを指定する
Preference取得方法:
4. PreferenceManager.getDefaultSharedPreferences から、SharedPreferencesを取得する
5. preferences.xmlに指定した key となる文字列を引数にして、設定値を取得する


これだけで実現できる。なんとも便利だ。
あとは、PreferenceScreenのxmlファイルを、書式に沿った書き方をすれば、
チェックボックスや、リストボックスや、テキストボックス等
結構色々な形式での入力方法をサポートしている。

PreferenceCategoryタグでくくることで、カテゴリ分けも可能
以下は、チェックボックスと、テキストボックスを含むpreferences.xmlファイル




 
 

 



以下は、Preferenceの取得コード
引数の2番目には、取得が失敗した時のデフォルト値が入る。


SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
boolean jspEnable = pref.getBoolean("checkbox", false);
string url = pref.getString("url1", "http://google.co.jp");

以下は、Preference用のアクティビティ

public class Preference extends PreferenceActivity
{
 @Override
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
 }
}