Android SQLite いろいろメモ

SQLiteのデータ型

INTEGER符号付整数
REAL浮動小数点
TEXTテキスト
BLOBバイナリデータ

システム日付を取得する

CURRENT_TIMESTAMP、CURRENT_DATE、CURRENT_TIMEはUTC(協定世界時)になる。
ローカルタイムゾーンの現在時刻はdatetime('now', 'localtime')で取得する。
insert into PFNAVIKNR (
    Cd,
    Name,
    Age,
    UpdDate
    ) values (1, 'yan', 24, datetime('now', 'localtime'))

テーブルを作成する

CREATE TABLE MyTable
(
    Cd          integer   NOT NULL,
    SeqNo       integer   NOT NULL,
    UpdDate     text,
    primary key(Cd,SeqNo)
)

テーブルを削除する

DROP TABLE MyTable

.NET ファイル読み込み時の注意点

以下のコードは
ファイルの存在チェックを行い、
ファイルが存在する場合はファイルの内容を読み込みます。
Dim path As String = "D:\test.csv"  '※D:\test.csvは存在するものとします。
'ファイルが存在するかどうか
Dim isExists As Boolean = System.IO.File.Exists(path)
Console.WriteLine("isExists:" & isExists)
'ファイル読み込み
If isExists = True Then
    Dim line() As String = System.IO.File.ReadAllLines(path)
End If

ファイルパスの「途中」に改行コードを追加すると、System.IO.File.Exists()メソッドはfalseを返します。
なので、ファイル読み込みは行われません。
Dim path As String = "D:\" & Environment.NewLine & "test.csv"


ファイルパスの「末尾」に改行コードを追加すると System.IO.File.Exists()メソッドはtrueを返します。
なので、ファイル読み込みが行われるのですが、System.IO.File.ReadAllLines()メソッドは例外「ArgumentExceptionp:パスに無効な文字が含まれます。」をスローします。
Dim path As String = "D:\test.csv" & Environment.NewLine


結論
ファイル存在チェックとは別にファイルに不正な文字が含まれているかチェックする必要がある。
Dim path As String = "D:\test.csv" & Environment.NewLine
'パスに無効な文字が含まれていないか
Dim isInvalidChars As Boolean = (path.IndexOfAny(System.IO.Path.GetInvalidPathChars) <> -1)
Console.WriteLine("isInvalidChars:" & isInvalidChars)
'ファイルが存在するかどうか
Dim isExists As Boolean = System.IO.File.Exists(path)
Console.WriteLine("isExists:" & isExists)
'ファイル読み込み
If isExists = True AndAlso isInvalidChars = True Then
    Dim line() As String = System.IO.File.ReadAllLines(path)
End If

Android Buttonの表示/非表示

Buttonの表示/非表示を設定するにはview#setVisibility(int visibility)メソッドを使用します。
引数には可視状態を表す定数を指定します。
view.VISIBLE・・・表示
view.INVISIBLE・・・非表示(非表示にしたスペースは詰めない)
view.GONE・・・非表示(非表示にしたスペースを詰める)

下記の画像はButton01を INVISIBLEとGONEで非表示にしたものです。

View.INVISIBLE

View.GONE

Button03をクリックするとButton01の可視状態を切り替えます。
package my.study.android;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivty extends Activity {
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        Button btn3 = (Button)this.findViewById(R.id.Button03);
        btn3.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                Button btn1 = (Button)MainActivty.this.findViewById(R.id.Button01);
                if (btn1.getVisibility() != View.VISIBLE) {
                    btn1.setVisibility(View.VISIBLE);
                } else {
                    btn1.setVisibility(View.INVISIBLE);
                }    
            }});
    }
}

レイアウト.xmlで可視状態を設定する場合は「android:visibility」で指定します。
<Button 
 android:id="@+id/Button01" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content" 
 android:text="Button01"
 android:visibility="gone">
</Button>

OeacleLite GroupBy句とOrderBy句は一緒に使えない

OracleLite10gで、GroupBy句とOrderBy句を一緒に使用するとソートされません。

以下のようなsqlはOrderBy句が無視されます。
SELECT hoge1, hoge2, hoge3
FROM table
GROUP BY hoge1, hoge2, hoge3
ORDER BY hoge3

この問題を回避するために、GroupBy句を副表にします。
SELECT hoge1, hoge2, hoge3
FROM (SELECT hoge1, hoge2, hoge3 FROM table GROUP BY hoge1, hoge2, hoge3)
ORDER BY hoge3

Android ボタンに画像とテキストを表示する



ImageButtonではなくButtonを使用します。

レイアウト.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout 
 android:id="@+id/LinearLayout01" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical">
    <Button 
  android:id="@+id/Button01" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:drawableTop="@drawable/icon" 
  android:text="Button01">
 </Button>
 <Button 
  android:id="@+id/Button02" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:drawableLeft="@drawable/icon" 
  android:text="Button02">
 </Button>
 <Button 
  android:id="@+id/Button03" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:drawableRight="@drawable/icon" 
  android:text="Button03">
 </Button>
 <Button 
  android:id="@+id/Button04" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content" 
  android:drawableBottom="@drawable/icon" 
  android:text="Button04">
 </Button>

</LinearLayout>

Android タブ画面を表示する

Tab画面を表示するには2つの方法があります。
1,TabActivityクラスを継承する方法
2,Activityクラスを継承する方法



TabActivityクラスを継承する方法

まずレイアウトを作成します。

レイアウトにはいくつか注意点があります。
1,TabHostのidは「@android:id/tabhost」にする。
2,TabHostにはTabWidgetを配置し、そのidは「@android:id/tabs」にする
3,TabHostにはFrameLayoutを配置し、そのidは「@android:id/tabcontent」にする
4,FrameLayout(tabcontent)はpaddingTopを65px~70pxに設定する。paddingTopを設定しないとタブとタブ内容が重なってしまいます。
res/layout/main1.xml
<?xml version="1.0" encoding="utf-8"?>
<TabHost 
 android:id="@android:id/tabhost" 
 android:layout_width="fill_parent" 
 android:layout_height="fill_parent" 
 xmlns:android="http://schemas.android.com/apk/res/android">
 
 <TabWidget 
  android:id="@android:id/tabs" 
  android:layout_width="wrap_content" 
  android:layout_height="wrap_content">
 </TabWidget>
 <FrameLayout 
  android:id="@android:id/tabcontent" 
  android:layout_height="fill_parent" 
  android:layout_width="fill_parent" 
  android:paddingTop="65px">
  <LinearLayout 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:id="@+id/content1">
   <CheckBox 
    android:text="@+id/CheckBox01" 
    android:id="@+id/CheckBox01" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
   </CheckBox>
  </LinearLayout>
  <LinearLayout 
   android:layout_width="wrap_content" 
   android:layout_height="wrap_content" 
   android:id="@+id/content2">
   <RadioButton 
    android:text="@+id/RadioButton01" 
    android:id="@+id/RadioButton01" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content">
   </RadioButton>
  </LinearLayout>
 </FrameLayout>
</TabHost>

MainActivityはTabActivityクラスを継承して作成します。
onCreate()メソッドで、getTabHost()メソッドでTabHostオブジェクトを取得し、Tabを追加します。

MainActivity.java
package my.study.android;

import android.app.TabActivity;
import android.os.Bundle;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

public class MainActivty extends TabActivity {
    
    private static String[] sTabId = {"Tab1","Tab2"};

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

        // TabHostオブジェクト取得
        TabHost tabs = getTabHost();

        // Tab1 設定
        TabSpec tab1 = tabs.newTabSpec(sTabId[0]);
        tab1.setIndicator("タブページ1");   
        tab1.setContent(R.id.content1); 
        tabs.addTab(tab1);    
        
        // Tab2 設定
        TabSpec tab2 = tabs.newTabSpec(sTabId[1]);
        tab2.setIndicator("タブページ2");   
        tab2.setContent(R.id.content2); 
        tabs.addTab(tab2);    
        
        // 初期表示設定
        tabs.setCurrentTab(0);
    }
}


Activityクラスを継承する作成する

まずレイアウトを作成します。「TabActivityクラスを継承する方法」と同じものを使用します。
レイアウトの注意点ですが、下記のうち1は必須ではありません。
1,TabHostのidは「@android:id/tabhost」にする。
2,TabHostにはTabWidgetを配置し、そのidは「@android:id/tabs」にする
3,TabHostにはFrameLayoutを配置し、そのidは「@android:id/tabcontent」にする
4,FrameLayout(tabcontent)はpaddingTopを65px~70pxに設定する。paddingTopを設定しないとタブとタブ内容が重なってしまいます。

MainActivityはActivityクラスを継承して作成します。
onCreate()メソッドで、findViewById()メソッドでTabHostオブジェクトを取得します。
Tabを追加する前に、tabhost#setup()メソッドでTabHostを初期化し、Tabを追加します。

MainActivity.java
package my.study.android;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

public class MainActivty extends Activity {
    
    private static String[] sTabId = {"Tab1","Tab2"};

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

        // TabHostオブジェクト取得
        //TabHost tabs = getTabHost();
        TabHost tabs = (TabHost)findViewById(android.R.id.tabhost);    
        tabs.setup();
        // Tab1 設定
        TabSpec tab1 = tabs.newTabSpec(sTabId[0]);
        tab1.setIndicator("タブページ1");   
        tab1.setContent(R.id.content1); 
        tabs.addTab(tab1);    
        // Tab2 設定
        TabSpec tab2 = tabs.newTabSpec(sTabId[1]);
        tab2.setIndicator("タブページ2");   
        tab2.setContent(R.id.content2); 
        tabs.addTab(tab2);    
        // 初期表示設定
        tabs.setCurrentTab(0);
    }
}

Android キャッチされなかった例外を処理する

Androidアプリでキャッチされなかった例外を処理する方法が下記のサイトに詳しく紹介されています。

throw Life - Androidアプリのバグ報告システムを考える
冬通りに消え行く制服ガールは、夢物語にリアルを求めない。 - Android でアプリケーションが強制終了したとき、エラーレポートを送るようにする

上記のリンクを参考に、例外のスタックトレースをメールで送信できるようにしてみます。

ボタンを押すと例外が発生し、アプリは強制終了します。

もう一度アプリを起動すると、バグレポートをメール送信するか確認メッセージを表示します。
Postボタンをタップすると、メールを送信します。



catchしなかった例外を補足するためにThread.UncaughtExceptionHandleを実装したCsUncaughtExceptionHandlerを作成します。
uncaughtException()メソッドで例外のスタックトレースをファイルに書き込みます。
SendBugReport()メソッドでファイルを読み込んでメールを送信します。
package my.study.android;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;

public class CsUncaughtExceptionHandler implements java.lang.Thread.UncaughtExceptionHandler {
    private static Context sContext = null;
    private static final String BUG_FILE = "BugReport";
    private static final UncaughtExceptionHandler sDefaultHandler 
             = Thread.getDefaultUncaughtExceptionHandler();
    
    /**
     * コンストラクタ
     * @param context
     */
    public CsUncaughtExceptionHandler(Context context){
        sContext = context;
    }

    /**
     * キャッチされない例外によって指定されたスレッドが終了したときに呼び出されます
     * 例外スタックトレースの内容をファイルに出力します
     */
    public void uncaughtException(Thread thread, Throwable ex) { 
        PrintWriter pw = null;   
        try {
            pw = new PrintWriter(sContext.openFileOutput(BUG_FILE, Context.MODE_WORLD_READABLE));
            ex.printStackTrace(pw); 
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (pw != null) pw.close();      
        }
        sDefaultHandler.uncaughtException(thread, ex);
    }
    
    /**
     * バグレポートの内容をメールで送信します。
     * @param activity
     */
    public static void SendBugReport(final Activity activity) {
        //バグレポートがなければ以降の処理を行いません。
        final File bugfile = activity.getFileStreamPath(BUG_FILE);
        if (!bugfile.exists()) {
            return;
        }    
        //AlertDialogを表示します。
        AlertDialog.Builder alert = new AlertDialog.Builder(activity);
        alert.setTitle("ERROR");
        alert.setMessage("予期しないエラーが発生しました。開発元にエラーを送信してください。");
        alert.setPositiveButton("Post", new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                SendMail(activity,bugfile);
            }});
        alert.setNegativeButton("Cancel", null);
        alert.show();
    }
    
    /**
     * バグレポートの内容をメールで送信します。
     * @param activity
     * @param bugfile
     */
    private static void SendMail(final Activity activity,File bugfile){
        //バグレポートの内容を読み込みます。
        StringBuilder sb = new StringBuilder();
        try {
            BufferedReader br = new BufferedReader(new FileReader(bugfile));
            String str;      
            while((str = br.readLine()) != null){      
                sb.append(str +"\n");     
            }       
        } catch (Exception e) {
            e.printStackTrace();
        }
        //メールで送信します。
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SENDTO);
        intent.setData(Uri.parse("mailto:" + "xxx@xxxx.xx.xx"));
        intent.putExtra(Intent.EXTRA_SUBJECT, "【BugReport】" + R.string.app_name );
        intent.putExtra(Intent.EXTRA_TEXT, sb.toString());
        activity.startActivity(intent);
        //バグレポートを削除します。
        bugfile.delete();
    }
    
}

スレッドでキャッチされなかった例外を捕捉するために、Thread.setDefaultUncaughtExceptionHandler()メソッドにCsUncaughtExceptionHandlerオブジェクトを設定します。
アプリで1度だけハンドラを設定すればいいので、一番最初に表示されるMainActivityのonCreate()メソッドで設定します。
CsUncaughtExceptionHandlerのコンストラクタの引数には、メモリリークが発生しないようgetApplicationContext()メソッドで取得したcontextを渡すようにします。
※アプリケーションで共通に使用するcontextに、現在のActivityを指定するとメモリが解放されない事があります。
こちらで詳しく書かれています。textdrop-Androidでのメモリリーク回避

MainActivityにはボタンを1つ配置し、タップするとArithmeticExceptionを発生します。

onStart()メソッドでは、CsUncaughtExceptionHandler.SendBugReport()メソッドを呼び出して、バグレポートがあればメールを送信するようにします。

package my.study.android;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //レイアウトを読み込みます
        this.setContentView(R.layout.main);
       
        //アプリケーションで共通に利用するオブジェクトには、メモリリークが発生しないようにthisではなく
        //Context.getApplicationContext()を使用します。
        Context context = this.getApplicationContext(); 
        //キャッチされない例外により、スレッドが突然終了したときや、
        //このスレッドに対してほかにハンドラが定義されていないときに
        //呼び出されるデフォルトのハンドラを設定します。
        Thread.setDefaultUncaughtExceptionHandler(new CsUncaughtExceptionHandler(context));

        //ボタンにOnClickListenerを設定します。
        Button btn = (Button)this.findViewById(R.id.btnThrowEx);
        btn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                int index = 5 / 0;  //ArithmeticExceptionを発生させる
            }});
    }

    @Override
    protected void onStart() {
        super.onStart();
        CsUncaughtExceptionHandler.SendBugReport(this);
    }
}

Android AlertDialogを表示する

基本的な使い方

タイトルとメッセージを表示するだけの基本的なAlertDialogです。
「戻る」ボタンで元の画面に戻ります。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
              
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setMessage("Message");
        alert.show();
    }  
}

OKダイアログ

次にOKボタンを表示し、ダイアログを閉じられるようにします。
OKボタンをクリックしたときに画面を閉じるだけの場合、setPositiveButton()メソッドの第2引数をnullにします。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
              
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setMessage("Message");
        alert.setPositiveButton("OK", null);
        alert.show();
    }  
}


Yes/Noダイアログ

Yesボタンを押したときの処理はsetPositiveButton()メソッドの第2引数にDialogInterface.OnClickListenerを設定して、処理を記述します。
Noボタンを押したときの処理はsetNegativeButton()メソッドの第2引数にDialogInterface.OnClickListenerを設定して、処理を記述します。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
              
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setMessage("Message");
        alert.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Yesボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Yes Clicked!", Toast.LENGTH_LONG).show();
            }});
        alert.setNegativeButton("No", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Noボタンが押された時の処理
                Toast.makeText(MainActivity.this, "No Clicked!", Toast.LENGTH_LONG).show();
            }});
        alert.show();
    }  
}

Yes/No/Cancelダイアログ

先ほどのYes/Noダイアログでは、setNegativeButton()メソッドにNoボタンを設定しましたが、
Yesボタン、Noボタン、Cancelボタンの順にボタンを配置したい場合は、
YesボタンはsetPositiveButton()、NoボタンはsetNeutralButton()、CancelボタンはsetNegativeButton()に処理を記述します。
setPositiveButton()メソッドで設定したボタンは一番左、setNeutralButton()メソッドで設定したボタンは中央、setNegativeButton()メソッドで設定したボタンは一番右に配置されます。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
              
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setMessage("Message");
        alert.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Yesボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Yes Clicked!", Toast.LENGTH_LONG).show();
            }});
            alert.setNeutralButton("No", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Noボタンが押された時の処理
                Toast.makeText(MainActivity.this, "No Clicked!", Toast.LENGTH_LONG).show();
            }});
        alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Cancelボタンが押された時の処理
    Toast.makeText(MainActivity.this, "Cancel Clicked!", Toast.LENGTH_LONG).show();
   }});
     alert.show();
    }  
}

ダイアログにリストを表示する

setItems()メソッドを使って、ダイアログにリストを表示させる事ができます。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
              
        final String[] items = {"item1","item2","item3"};
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setItems(items, new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int idx) {
                // リストアイテムを選択したときの処理
                Toast.makeText(MainActivity.this, String.format("%s Selected", items[idx]), Toast.LENGTH_LONG).show();
            }});
        alert.show();
    }  
}

ダイアログにラジオボタン付きのリストを表示する

setSingleChoiceItems()メソッドを使って、ダイアログにラジオボタン付きのリストを表示できます。
setSingleChoiceItems()メソッドの第1引数にはリストに表示する項目の配列、第2引数には選択するラジオボタンの初期値を指定します。初期値に-1を選択すると何も選択されません。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
    
    private int mCheckedItem = -1;
 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
               
        final String[] items = {"item1","item2","item3"};
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setSingleChoiceItems(items,mCheckedItem,new DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, String.format("%s Selected", items[which]), Toast.LENGTH_LONG).show();
                mCheckedItem = which;
            }});
        alert.setPositiveButton("OK", new  DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, String.format("%s Selected", items[mCheckedItem]), Toast.LENGTH_LONG).show();
            }});
        alert.show();
    }  
}

ダイアログにチェックボックス付きのリストを表示する

setMultiChoiceItems()メソッドを使って、複数選択できるチェックボックス付きのリストを表示することができます。
setMultiChoiceItems()メソッドの第1引数にはリストに表示する項目の配列、第2引数には選択するチェックボックスの初期値を論理値配列で指定します。

package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {
    
    private boolean[] mCheckedItems = {true,false,true};
 
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
               
        final String[] items = {"item1","item2","item3"};
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        alert.setMultiChoiceItems(items, mCheckedItems, new DialogInterface.OnMultiChoiceClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                mCheckedItems[which] = isChecked; 
            }});
        alert.setPositiveButton("OK", new  DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int idx) {
                String str =  null;
                for (int i = 0; i < mCheckedItems.length; i++){
                    if (mCheckedItems[i] == true){
                        str += items[i];
                    }
                }
                if (str == null){
                    str = "No Selected";
                }
                Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
            }});
        alert.show();
    }  
}

独自のレイアウトを表示する

AlertDialogに独自のレイアウトを表示することもできます。


まずAlertDialogに表示するレイアウトを作成します。
EditTextを1つ配置したレイアウトを作成しました。
res/layout/alert.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
  
 <EditText android:id="@+id/EditText01" 
 android:layout_height="wrap_content" 
 android:layout_width="fill_parent">
 </EditText>

</LinearLayout>
LayoutInflaterクラスを使用して、レイアウトからViewを作成し、AlertDialog#setView()メソッドでViewを設定します。
MainActivity.java
package my.study.android;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity { 
  
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        AlertDialog.Builder alert = new AlertDialog.Builder(this);
        alert.setTitle("Title");
        //LayoutInflaterクラスを使用して、レイアウトからViewを作成します。
        LayoutInflater inflater = LayoutInflater.from(this);
        final View viw = inflater.inflate(R.layout.alert,null);  
        //AlertDialogにビューを設定します。
        alert.setView(viw);   
        alert.setPositiveButton("OK", new  DialogInterface.OnClickListener(){
            @Override
            public void onClick(DialogInterface dialog, int idx) {
                EditText txt = (EditText)viw.findViewById(R.id.EditText01);
                Toast.makeText(MainActivity.this,txt.getText(),Toast.LENGTH_LONG).show();
            }});
        alert.show();
    }  
}