Sqliteメモ

select の結果を見やすく成形する。

.header On
.mode column

実機上のデータベースデータを読み込む

テスト用途限定。
/data 以下のファイルは root 化しなければ読み取ることができないため SD カード上にデータを配置する方式を取る。

  • AndroidManifest.xml に以下の権限情報を追加する。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  • SQLiteOpenHelper などに渡すデータベース名を以下のようにSDカード上の任意の場所にする。
Environment.getExternalStorageDirectory () + "/data/mydatabase.db";
  • データベースが生成されると以下のようにdbファイルが確認できる。
C:\>adb shell ls sdcard/data/
mydatabase.db
C:\>adb shell pull /mnt/sdcard/data/mydatabase.db
1632 KB/s (156672 bytes in 0.093s)

ウィンドウのタイトルバーを非表示にする方法

以下の2つの方法があるらしい。

themeを使う方法

AndroidManifest.xml ファイルの application 要素や activity 要素に以下を指定。

android:theme="@android:style/Theme.Black.NoTitleBar"

背景は黒とか透明とか任意のものを利用可能です。

Activity#setContentView()を使う方法

onCreate()メソッド等で Activity#setContentView() が呼ばれる前に下記を呼び出すをする。

this.requestWindowFeature(Window.FEATURE_NO_TITLE)

でもおいらの環境だとなぜか一瞬タイトルが表示されます(´・ω・`)

ListActivity サンプル

ListActivityとArrayAdapterを使用したシンプルなリスト

ListViewActivity01

package com.objectfanatics.android.prj00019;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

/**
 * Activity 全体を ListView として扱うために ListActivity を継承しています。setContentView(int) を呼び出す必要がないのでコードが単純になります。
 */
public class ListViewActivity01 extends ListActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	  super.onCreate(savedInstanceState);
    	  
    	  // リストに表示する国名の配列を文字列リソースから取得します。
    	  String[] countryNamesList = getResources().getStringArray (R.array.country_names_list);

    	  // ArrayAdapter はオブジェクトの配列をリストの要素として扱うためのクラスです。
    	  // 型変数には配列の要素の型が入ります。今回は文字列を扱うために <String> が指定されています。
    	  // 第一引数は Context なので this を渡しています。
    	  // 第二引数は各行の表示に対応するレイアウトを含んでいるレイアウトファイルのリソース ID なので今回は layout/listview_01_list_item.xml ファイルを作成して指定しています。
    	  // 第三引数は ListView に表示される文字列の配列を指定します。
    	  ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.listview_01_list_item, countryNamesList);
    	  
    	  // ListView に ArrayAdapter を渡すことにより、ListView は表示する内容を認識します。
    	  setListAdapter(arrayAdapter);
    }
}

listview_01_list_item.xml

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

strings.xml

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

    <string-array
        name="country_names_list">
        <item>Afghanistan</item>
        <item>Albania</item>
        <item>Algeria</item>
        <item>American Samoa</item>
        <item>Andorra</item>
        <item>Angola</item>
        <item>Anguilla</item>
        <item>Antarctica</item>
        <item>Antigua and Barbuda</item>
        <item>Argentina</item>
        <item>Armenia</item>
        <item>Aruba</item>
        <item>Australia</item>
        <item>Austria</item>
        <item>Azerbaijan</item>
        <item>Bahrain</item>
        <item>Bangladesh</item>
        <item>Barbados</item>
        <item>Belarus</item>
        <item>Belgium</item>
        <item>Belize</item>
        <item>Benin</item>
        <item>Bermuda</item>
        <item>Bhutan</item>
        <item>Bolivia</item>
        <item>BosniaandHerzegovina</item>
        <item>Botswana</item>
        <item>BouvetIsland</item>
        <item>Brazil</item>
        <item>BritishIndianOceanTerritory</item>
        <item>BritishVirginIslands</item>
        <item>Brunei</item>
        <item>Bulgaria</item>
        <item>BurkinaFaso</item>
        <item>Burundi</item>
        <item>Coted\'Ivoire</item>
        <item>Cambodia</item>
        <item>Cameroon</item>
        <item>Canada</item>
        <item>CapeVerde</item>
        <item>CaymanIslands</item>
        <item>CentralAfricanRepublic</item>
        <item>Chad</item>
        <item>Chile</item>
        <item>China</item>
        <item>ChristmasIsland</item>
        <item>Cocos(Keeling)Islands</item>
        <item>Colombia</item>
        <item>Comoros</item>
        <item>Congo</item>
        <item>CookIslands</item>
        <item>CostaRica</item>
        <item>Croatia</item>
        <item>Cuba</item>
        <item>Cyprus</item>
        <item>CzechRepublic</item>
        <item>DemocraticRepublicoftheCongo</item>
        <item>Denmark</item>
        <item>Djibouti</item>
        <item>Dominica</item>
        <item>DominicanRepublic</item>
        <item>EastTimor</item>
        <item>Ecuador</item>
        <item>Egypt</item>
        <item>ElSalvador</item>
        <item>EquatorialGuinea</item>
        <item>Eritrea</item>
        <item>Estonia</item>
        <item>Ethiopia</item>
        <item>FaeroeIslands</item>
        <item>FalklandIslands</item>
        <item>Fiji</item>
        <item>Finland</item>
        <item>FormerYugoslavRepublicofMacedonia</item>
        <item>France</item>
        <item>FrenchGuiana</item>
        <item>FrenchPolynesia</item>
        <item>FrenchSouthernTerritories</item>
        <item>Gabon</item>
        <item>Georgia</item>
        <item>Germany</item>
        <item>Ghana</item>
        <item>Gibraltar</item>
        <item>Greece</item>
        <item>Greenland</item>
        <item>Grenada</item>
        <item>Guadeloupe</item>
        <item>Guam</item>
        <item>Guatemala</item>
        <item>Guinea</item>
        <item>Guinea-Bissau</item>
        <item>Guyana</item>
        <item>Haiti</item>
        <item>HeardIslandandMcDonaldIslands</item>
        <item>Honduras</item>
        <item>HongKong</item>
        <item>Hungary</item>
        <item>Iceland</item>
        <item>India</item>
        <item>Indonesia</item>
        <item>Iran</item>
        <item>Iraq</item>
        <item>Ireland</item>
        <item>Israel</item>
        <item>Italy</item>
        <item>Jamaica</item>
        <item>Japan</item>
        <item>Jordan</item>
        <item>Kazakhstan</item>
        <item>Kenya</item>
        <item>Kiribati</item>
        <item>Kuwait</item>
        <item>Kyrgyzstan</item>
        <item>Laos</item>
        <item>Latvia</item>
        <item>Lebanon</item>
        <item>Lesotho</item>
        <item>Liberia</item>
        <item>Libya</item>
        <item>Liechtenstein</item>
        <item>Lithuania</item>
        <item>Luxembourg</item>
        <item>Macau</item>
        <item>Madagascar</item>
        <item>Malawi</item>
        <item>Malaysia</item>
        <item>Maldives</item>
        <item>Mali</item>
        <item>Malta</item>
        <item>MarshallIslands</item>
        <item>Martinique</item>
        <item>Mauritania</item>
        <item>Mauritius</item>
        <item>Mayotte</item>
        <item>Mexico</item>
        <item>Micronesia</item>
        <item>Moldova</item>
        <item>Monaco</item>
        <item>Mongolia</item>
        <item>Montserrat</item>
        <item>Morocco</item>
        <item>Mozambique</item>
        <item>Myanmar</item>
        <item>Namibia</item>
        <item>Nauru</item>
        <item>Nepal</item>
        <item>Netherlands</item>
        <item>NetherlandsAntilles</item>
        <item>NewCaledonia</item>
        <item>NewZealand</item>
        <item>Nicaragua</item>
        <item>Niger</item>
        <item>Nigeria</item>
        <item>Niue</item>
        <item>NorfolkIsland</item>
        <item>NorthKorea</item>
        <item>NorthernMarianas</item>
        <item>Norway</item>
        <item>Oman</item>
        <item>Pakistan</item>
        <item>Palau</item>
        <item>Panama</item>
        <item>PapuaNewGuinea</item>
        <item>Paraguay</item>
        <item>Peru</item>
        <item>Philippines</item>
        <item>PitcairnIslands</item>
        <item>Poland</item>
        <item>Portugal</item>
        <item>PuertoRico</item>
        <item>Qatar</item>
        <item>Reunion</item>
        <item>Romania</item>
        <item>Russia</item>
        <item>Rwanda</item>
        <item>SqoTomeandPrincipe</item>
        <item>SaintHelena</item>
        <item>SaintKittsandNevis</item>
        <item>SaintLucia</item>
        <item>SaintPierreandMiquelon</item>
        <item>SaintVincentandtheGrenadines</item>
        <item>Samoa</item>
        <item>SanMarino</item>
        <item>SaudiArabia</item>
        <item>Senegal</item>
        <item>Seychelles</item>
        <item>SierraLeone</item>
        <item>Singapore</item>
        <item>Slovakia</item>
        <item>Slovenia</item>
        <item>SolomonIslands</item>
        <item>Somalia</item>
        <item>SouthAfrica</item>
        <item>SouthGeorgiaandtheSouthSandwichIslands</item>
        <item>SouthKorea</item>
        <item>Spain</item>
        <item>SriLanka</item>
        <item>Sudan</item>
        <item>Suriname</item>
        <item>SvalbardandJanMayen</item>
        <item>Swaziland</item>
        <item>Sweden</item>
        <item>Switzerland</item>
        <item>Syria</item>
        <item>Taiwan</item>
        <item>Tajikistan</item>
        <item>Tanzania</item>
        <item>Thailand</item>
        <item>TheBahamas</item>
        <item>TheGambia</item>
        <item>Togo</item>
        <item>Tokelau</item>
        <item>Tonga</item>
        <item>TrinidadandTobago</item>
        <item>Tunisia</item>
        <item>Turkey</item>
        <item>Turkmenistan</item>
        <item>TurksandCaicosIslands</item>
        <item>Tuvalu</item>
        <item>VirginIslands</item>
        <item>Uganda</item>
        <item>Ukraine</item>
        <item>UnitedArabEmirates</item>
        <item>UnitedKingdom</item>
        <item>UnitedStates</item>
        <item>UnitedStatesMinorOutlyingIslands</item>
        <item>Uruguay</item>
        <item>Uzbekistan</item>
        <item>Vanuatu</item>
        <item>VaticanCity</item>
        <item>Venezuela</item>
        <item>Vietnam</item>
        <item>WallisandFutuna</item>
        <item>WesternSahara</item>
        <item>Yemen</item>
        <item>Yugoslavia</item>
        <item>Zambia</item>
        <item>Zimbabwe</item>
    </string-array>
</resources>

ListViewActivity01 を継承し、リストの要素をクリックされた場合の振る舞いを追加したもの

ListViewActivity02.java

package com.objectfanatics.android.prj00019;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

/**
 * ListViewActivity01 を継承し、リストの要素をクリックされた場合の振る舞いを追加しています。
 */
public class ListViewActivity02 extends ListViewActivity01 {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// この Activity に対応する ListView を取得
		ListView lv = getListView();

		// ListView のアイテムがクリックされた場合の振る舞いを登録
		lv.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				
				// 指定された行の文字列を取得
				CharSequence rowString = ((TextView) view).getText();

				// クリックされたら対応する文字列を Toast で表示
				Toast.makeText(getApplicationContext(), rowString, Toast.LENGTH_SHORT).show();
			}
		});
	}
}

ListView の各行に 独自に定義した TextView を使用

ListViewActivity03

package com.objectfanatics.android.prj00019;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

/**
 * ListView の各行に 独自に定義した TextView を使用しています。
 */
public class ListViewActivity03 extends ListActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// リストに表示する国名の配列を文字列リソースから取得します。
		final String[] countryNamesList = getResources().getStringArray(R.array.country_names_list);

		// ArrayAdapter はオブジェクトの配列をリストの要素として扱うためのクラスです。
		// 型変数には配列の要素の型が入ります。今回は文字列を扱うために <String> が指定されています。
		// 第一引数は Context なので this を渡しています。
		// 第二引数は各行の表示に対応するレイアウトを含んでいるレイアウトファイルのリソース ID なので今回は
		// layout/listview_01_list_item.xml ファイルを作成して指定しています。
		// 第三引数は ListView に表示される文字列の配列を指定します。
		ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.listview_01_list_item, countryNamesList) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				// ビューを受け取る  
				TextView textView = (TextView)convertView;  
				if (textView == null) {  
					// 受け取ったビューがnullなら新しくビューを生成  
					textView = (TextView)((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.row_01, null); 
				}
				textView.setText(countryNamesList[position]);
				return textView;
			}
		};

		// ListView に ArrayAdapter を渡すことにより、ListView は表示する内容を認識します。
		setListAdapter(arrayAdapter);
	}
}

row_01.xml

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

ListView の各行に ImageView や TextView を組み合わせた独自の View を使用した例

ListViewActivity04

package com.objectfanatics.android.prj00019;

import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

/**
 * ListView の各行に ImageView や TextView を組み合わせた独自の View を使用しています。
 */
public class ListViewActivity04 extends ListActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// リストに表示する国名の配列を文字列リソースから取得します。
		final String[] countryNamesList = getResources().getStringArray(R.array.country_names_list);

		// ArrayAdapter はオブジェクトの配列をリストの要素として扱うためのクラスです。
		// 型変数には配列の要素の型が入ります。今回は文字列を扱うために <String> が指定されています。
		// 第一引数は Context なので this を渡しています。
		// 第二引数は各行の表示に対応するレイアウトを含んでいるレイアウトファイルのリソース ID なので今回は
		// layout/listview_01_list_item.xml ファイルを作成して指定しています。
		// 第三引数は ListView に表示される文字列の配列を指定します。
		ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.row_02, countryNamesList) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				
				if (convertView == null) {  
					// 受け取ったビューがnullなら新しくビューを生成  
					convertView = (View)((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.row_02, null); 
				}
				TextView textView = (TextView)convertView.findViewById(R.id.row_02_textView);
				textView.setText(countryNamesList[position]);
				return convertView;
			}
		};

		// ListView に ArrayAdapter を渡すことにより、ListView は表示する内容を認識します。
		setListAdapter(arrayAdapter);
	}
}

row_02.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/icon" />
    <TextView
        android:id="@+id/row_02_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

システムのデフォルトのアイコンとその名前を表示するサンプル

ListViewActivity05.java

package com.objectfanatics.android.prj00019;

import android.app.ListActivity;
import android.content.Context;
import android.content.res.Resources.NotFoundException;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * システムのデフォルトのアイコンとその名前を表示します。
 */
public class ListViewActivity05 extends ListActivity {
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		ArrayAdapter<ImageResource> arrayAdapter = new ArrayAdapter<ImageResource>(this, R.layout.listview_01_list_item, imageResources) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				
				// View が null の場合
				if (convertView == null) {  
					
					// View が null のため新しくビューを生成する
					convertView = (View)((LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.row_03, null); 
				}
				
				// アイコンを表示するための view を取得する
				ImageView iconImageView = (ImageView)convertView.findViewById(R.id.iconImageView);
				
				try {
					// 表示すべき Drawable を取得する。対象が存在しない場合は NotFoundException がスローされる
					getResources().getDrawable(imageResources[position].id);
					iconImageView.setImageResource(imageResources[position].id);
				} catch (NotFoundException e) {
					// 対象の Drawable が存在しないため、代わりに R.drawable.icon を表示する。
					Log.d("", "Resource " + imageResources[position].name + " Not Found.");
					iconImageView.setImageResource(R.drawable.icon);
				}
				TextView textView = (TextView)convertView.findViewById(R.id.textImageView);
				textView.setText(imageResources[position].name);
					
				return convertView;
			}
		};

		setListAdapter(arrayAdapter);
	}
	
	private final ImageResource[] imageResources = new ImageResource[] {
		new ImageResource("alert_dark_frame", android.R.drawable.alert_dark_frame),
		new ImageResource("alert_light_frame", android.R.drawable.alert_light_frame),
		new ImageResource("arrow_down_float", android.R.drawable.arrow_down_float),
		new ImageResource("arrow_up_float", android.R.drawable.arrow_up_float),
		new ImageResource("bottom_bar", android.R.drawable.bottom_bar),
		new ImageResource("btn_default", android.R.drawable.btn_default),
		new ImageResource("btn_default_small", android.R.drawable.btn_default_small),
		new ImageResource("btn_dialog", android.R.drawable.btn_dialog),
		new ImageResource("btn_dropdown", android.R.drawable.btn_dropdown),
		new ImageResource("btn_minus", android.R.drawable.btn_minus),
		new ImageResource("btn_plus", android.R.drawable.btn_plus),
		new ImageResource("btn_radio", android.R.drawable.btn_radio),
		new ImageResource("btn_star", android.R.drawable.btn_star),
		new ImageResource("btn_star_big_off", android.R.drawable.btn_star_big_off),
		new ImageResource("btn_star_big_on", android.R.drawable.btn_star_big_on),
		new ImageResource("button_onoff_indicator_off", android.R.drawable.button_onoff_indicator_off),
		new ImageResource("button_onoff_indicator_on", android.R.drawable.button_onoff_indicator_on),
		new ImageResource("checkbox_off_background", android.R.drawable.checkbox_off_background),
		new ImageResource("checkbox_on_background", android.R.drawable.checkbox_on_background),
		new ImageResource("dark_header", android.R.drawable.dark_header),
		new ImageResource("dialog_frame", android.R.drawable.dialog_frame),
//			new ImageResource("dialog_holo_dark_frame", android.R.drawable.dialog_holo_dark_frame),
//			new ImageResource("dialog_holo_light_frame", android.R.drawable.dialog_holo_light_frame),
		new ImageResource("divider_horizontal_bright", android.R.drawable.divider_horizontal_bright),
		new ImageResource("divider_horizontal_dark", android.R.drawable.divider_horizontal_dark),
		new ImageResource("divider_horizontal_dim_dark", android.R.drawable.divider_horizontal_dim_dark),
		new ImageResource("divider_horizontal_textfield", android.R.drawable.divider_horizontal_textfield),
		new ImageResource("edit_text", android.R.drawable.edit_text),
		new ImageResource("editbox_background", android.R.drawable.editbox_background),
		new ImageResource("editbox_background_normal", android.R.drawable.editbox_background_normal),
		new ImageResource("editbox_dropdown_dark_frame", android.R.drawable.editbox_dropdown_dark_frame),
		new ImageResource("editbox_dropdown_light_frame", android.R.drawable.editbox_dropdown_light_frame),
		new ImageResource("gallery_thumb", android.R.drawable.gallery_thumb),
		new ImageResource("ic_btn_speak_now", android.R.drawable.ic_btn_speak_now),
		new ImageResource("ic_delete", android.R.drawable.ic_delete),
		new ImageResource("ic_dialog_alert", android.R.drawable.ic_dialog_alert),
		new ImageResource("ic_dialog_dialer", android.R.drawable.ic_dialog_dialer),
		new ImageResource("ic_dialog_email", android.R.drawable.ic_dialog_email),
		new ImageResource("ic_dialog_info", android.R.drawable.ic_dialog_info),
		new ImageResource("ic_dialog_map", android.R.drawable.ic_dialog_map),
		new ImageResource("ic_input_add", android.R.drawable.ic_input_add),
		new ImageResource("ic_input_delete", android.R.drawable.ic_input_delete),
		new ImageResource("ic_input_get", android.R.drawable.ic_input_get),
		new ImageResource("ic_lock_idle_alarm", android.R.drawable.ic_lock_idle_alarm),
		new ImageResource("ic_lock_idle_charging", android.R.drawable.ic_lock_idle_charging),
		new ImageResource("ic_lock_idle_lock", android.R.drawable.ic_lock_idle_lock),
		new ImageResource("ic_lock_idle_low_battery", android.R.drawable.ic_lock_idle_low_battery),
		new ImageResource("ic_lock_lock", android.R.drawable.ic_lock_lock),
		new ImageResource("ic_lock_power_off", android.R.drawable.ic_lock_power_off),
		new ImageResource("ic_lock_silent_mode", android.R.drawable.ic_lock_silent_mode),
		new ImageResource("ic_lock_silent_mode_off", android.R.drawable.ic_lock_silent_mode_off),
		new ImageResource("ic_media_ff", android.R.drawable.ic_media_ff),
		new ImageResource("ic_media_next", android.R.drawable.ic_media_next),
		new ImageResource("ic_media_pause", android.R.drawable.ic_media_pause),
		new ImageResource("ic_media_play", android.R.drawable.ic_media_play),
		new ImageResource("ic_media_previous", android.R.drawable.ic_media_previous),
		new ImageResource("ic_media_rew", android.R.drawable.ic_media_rew),
		new ImageResource("ic_menu_add", android.R.drawable.ic_menu_add),
		new ImageResource("ic_menu_agenda", android.R.drawable.ic_menu_agenda),
		new ImageResource("ic_menu_always_landscape_portrait", android.R.drawable.ic_menu_always_landscape_portrait),
		new ImageResource("ic_menu_call", android.R.drawable.ic_menu_call),
		new ImageResource("ic_menu_camera", android.R.drawable.ic_menu_camera),
		new ImageResource("ic_menu_close_clear_cancel", android.R.drawable.ic_menu_close_clear_cancel),
		new ImageResource("ic_menu_compass", android.R.drawable.ic_menu_compass),
		new ImageResource("ic_menu_crop", android.R.drawable.ic_menu_crop),
		new ImageResource("ic_menu_day", android.R.drawable.ic_menu_day),
		new ImageResource("ic_menu_delete", android.R.drawable.ic_menu_delete),
		new ImageResource("ic_menu_directions", android.R.drawable.ic_menu_directions),
		new ImageResource("ic_menu_edit", android.R.drawable.ic_menu_edit),
		new ImageResource("ic_menu_gallery", android.R.drawable.ic_menu_gallery),
		new ImageResource("ic_menu_help", android.R.drawable.ic_menu_help),
		new ImageResource("ic_menu_info_details", android.R.drawable.ic_menu_info_details),
		new ImageResource("ic_menu_manage", android.R.drawable.ic_menu_manage),
		new ImageResource("ic_menu_mapmode", android.R.drawable.ic_menu_mapmode),
		new ImageResource("ic_menu_month", android.R.drawable.ic_menu_month),
		new ImageResource("ic_menu_more", android.R.drawable.ic_menu_more),
		new ImageResource("ic_menu_my_calendar", android.R.drawable.ic_menu_my_calendar),
		new ImageResource("ic_menu_mylocation", android.R.drawable.ic_menu_mylocation),
		new ImageResource("ic_menu_myplaces", android.R.drawable.ic_menu_myplaces),
		new ImageResource("ic_menu_preferences", android.R.drawable.ic_menu_preferences),
		new ImageResource("ic_menu_recent_history", android.R.drawable.ic_menu_recent_history),
		new ImageResource("ic_menu_report_image", android.R.drawable.ic_menu_report_image),
		new ImageResource("ic_menu_revert", android.R.drawable.ic_menu_revert),
		new ImageResource("ic_menu_rotate", android.R.drawable.ic_menu_rotate),
		new ImageResource("ic_menu_save", android.R.drawable.ic_menu_save),
		new ImageResource("ic_menu_search", android.R.drawable.ic_menu_search),
		new ImageResource("ic_menu_send", android.R.drawable.ic_menu_send),
		new ImageResource("ic_menu_set_as", android.R.drawable.ic_menu_set_as),
		new ImageResource("ic_menu_share", android.R.drawable.ic_menu_share),
		new ImageResource("ic_menu_slideshow", android.R.drawable.ic_menu_slideshow),
		new ImageResource("ic_menu_sort_alphabetically", android.R.drawable.ic_menu_sort_alphabetically),
		new ImageResource("ic_menu_sort_by_size", android.R.drawable.ic_menu_sort_by_size),
		new ImageResource("ic_menu_today", android.R.drawable.ic_menu_today),
		new ImageResource("ic_menu_upload", android.R.drawable.ic_menu_upload),
		new ImageResource("ic_menu_upload_you_tube", android.R.drawable.ic_menu_upload_you_tube),
		new ImageResource("ic_menu_view", android.R.drawable.ic_menu_view),
		new ImageResource("ic_menu_week", android.R.drawable.ic_menu_week),
		new ImageResource("ic_menu_zoom", android.R.drawable.ic_menu_zoom),
		new ImageResource("ic_notification_clear_all", android.R.drawable.ic_notification_clear_all),
		new ImageResource("ic_notification_overlay", android.R.drawable.ic_notification_overlay),
		new ImageResource("ic_partial_secure", android.R.drawable.ic_partial_secure),
		new ImageResource("ic_popup_disk_full", android.R.drawable.ic_popup_disk_full),
		new ImageResource("ic_popup_reminder", android.R.drawable.ic_popup_reminder),
		new ImageResource("ic_popup_sync", android.R.drawable.ic_popup_sync),
		new ImageResource("ic_search_category_default", android.R.drawable.ic_search_category_default),
		new ImageResource("ic_secure", android.R.drawable.ic_secure),
		new ImageResource("list_selector_background", android.R.drawable.list_selector_background),
		new ImageResource("menu_frame", android.R.drawable.menu_frame),
		new ImageResource("menu_full_frame", android.R.drawable.menu_full_frame),
		new ImageResource("menuitem_background", android.R.drawable.menuitem_background),
		new ImageResource("picture_frame", android.R.drawable.picture_frame),
//			new ImageResource("presence_audio_away", android.R.drawable.presence_audio_away),
//			new ImageResource("presence_audio_busy", android.R.drawable.presence_audio_busy),
//			new ImageResource("presence_audio_online", android.R.drawable.presence_audio_online),
		new ImageResource("presence_away", android.R.drawable.presence_away),
		new ImageResource("presence_busy", android.R.drawable.presence_busy),
		new ImageResource("presence_invisible", android.R.drawable.presence_invisible),
		new ImageResource("presence_offline", android.R.drawable.presence_offline),
		new ImageResource("presence_online", android.R.drawable.presence_online),
//			new ImageResource("presence_video_away", android.R.drawable.presence_video_away),
//			new ImageResource("presence_video_busy", android.R.drawable.presence_video_busy),
//			new ImageResource("presence_video_online", android.R.drawable.presence_video_online),
		new ImageResource("progress_horizontal", android.R.drawable.progress_horizontal),
		new ImageResource("progress_indeterminate_horizontal", android.R.drawable.progress_indeterminate_horizontal),
		new ImageResource("radiobutton_off_background", android.R.drawable.radiobutton_off_background),
		new ImageResource("radiobutton_on_background", android.R.drawable.radiobutton_on_background),
		new ImageResource("screen_background_dark", android.R.drawable.screen_background_dark),
//			new ImageResource("screen_background_dark_transparent", android.R.drawable.screen_background_dark_transparent),
		new ImageResource("screen_background_light", android.R.drawable.screen_background_light),
//			new ImageResource("screen_background_light_transparent", android.R.drawable.screen_background_light_transparent),
		new ImageResource("spinner_background", android.R.drawable.spinner_background),
		new ImageResource("spinner_dropdown_background", android.R.drawable.spinner_dropdown_background),
		new ImageResource("star_big_off", android.R.drawable.star_big_off),
		new ImageResource("star_big_on", android.R.drawable.star_big_on),
		new ImageResource("star_off", android.R.drawable.star_off),
		new ImageResource("star_on", android.R.drawable.star_on),
		new ImageResource("stat_notify_call_mute", android.R.drawable.stat_notify_call_mute),
		new ImageResource("stat_notify_chat", android.R.drawable.stat_notify_chat),
		new ImageResource("stat_notify_error", android.R.drawable.stat_notify_error),
		new ImageResource("stat_notify_missed_call", android.R.drawable.stat_notify_missed_call),
		new ImageResource("stat_notify_more", android.R.drawable.stat_notify_more),
		new ImageResource("stat_notify_sdcard", android.R.drawable.stat_notify_sdcard),
//			new ImageResource("stat_notify_sdcard_prepare", android.R.drawable.stat_notify_sdcard_prepare),
		new ImageResource("stat_notify_sdcard_usb", android.R.drawable.stat_notify_sdcard_usb),
		new ImageResource("stat_notify_sync", android.R.drawable.stat_notify_sync),
		new ImageResource("stat_notify_sync_noanim", android.R.drawable.stat_notify_sync_noanim),
		new ImageResource("stat_notify_voicemail", android.R.drawable.stat_notify_voicemail),
		new ImageResource("stat_sys_data_bluetooth", android.R.drawable.stat_sys_data_bluetooth),
		new ImageResource("stat_sys_download", android.R.drawable.stat_sys_download),
		new ImageResource("stat_sys_download_done", android.R.drawable.stat_sys_download_done),
		new ImageResource("stat_sys_headset", android.R.drawable.stat_sys_headset),
		new ImageResource("stat_sys_phone_call", android.R.drawable.stat_sys_phone_call),
		new ImageResource("stat_sys_phone_call_forward", android.R.drawable.stat_sys_phone_call_forward),
		new ImageResource("stat_sys_phone_call_on_hold", android.R.drawable.stat_sys_phone_call_on_hold),
		new ImageResource("stat_sys_speakerphone", android.R.drawable.stat_sys_speakerphone),
		new ImageResource("stat_sys_upload", android.R.drawable.stat_sys_upload),
		new ImageResource("stat_sys_upload_done", android.R.drawable.stat_sys_upload_done),
//			new ImageResource("stat_sys_vp_phone_call", android.R.drawable.stat_sys_vp_phone_call),
//			new ImageResource("stat_sys_vp_phone_call_on_hold", android.R.drawable.stat_sys_vp_phone_call_on_hold),
		new ImageResource("stat_sys_warning", android.R.drawable.stat_sys_warning),
		new ImageResource("status_bar_item_app_background", android.R.drawable.status_bar_item_app_background),
		new ImageResource("status_bar_item_background", android.R.drawable.status_bar_item_background),
		new ImageResource("sym_action_call", android.R.drawable.sym_action_call),
		new ImageResource("sym_action_chat", android.R.drawable.sym_action_chat),
		new ImageResource("sym_action_email", android.R.drawable.sym_action_email),
		new ImageResource("sym_call_incoming", android.R.drawable.sym_call_incoming),
		new ImageResource("sym_call_missed", android.R.drawable.sym_call_missed),
		new ImageResource("sym_call_outgoing", android.R.drawable.sym_call_outgoing),
		new ImageResource("sym_contact_card", android.R.drawable.sym_contact_card),
		new ImageResource("sym_def_app_icon", android.R.drawable.sym_def_app_icon),
		new ImageResource("title_bar", android.R.drawable.title_bar),
		new ImageResource("title_bar_tall", android.R.drawable.title_bar_tall),
		new ImageResource("toast_frame", android.R.drawable.toast_frame),
		new ImageResource("zoom_plate", android.R.drawable.zoom_plate),
	};
	
	/**
	 * 表示するイメージの名前とIDを持つクラス
	 */
	private class ImageResource {
		private final String name;
		private final int id;
		public ImageResource(String name, int id) {
			this.name = name;
			this.id = id;
		}
	}
}

row_03.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iconImageView"
        android:layout_width="25sp"
        android:layout_height="25sp"
        android:layout_marginRight="5sp"
        />
    <TextView
        android:id="@+id/textImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

perlで文字列を置換する方法

sedだと最短マッチができないのでperlを使用。

サンプルファイル(string.txt)

string.txt ファイルには以下の文字列が格納されているとします。

abcabc
defdeF
deFdef
ghighi

正規表現にマッチした文字列を置換するコマンドライン入力例

perl -p -e "s/正規表現/置換後の文字列/g" string.txt

置換の例

例. dで始まりfで終わる文字列への最長マッチ(行単位)

$ perl -p -e "s/d.+f/[replaced]/" string.txt
abcabc
[replaced]deF
[replaced]
ghighi

例. 上記の例の大文字小文字を無視

$ perl -p -e "s/d.+f/[replaced]/i" string.txt
abcabc
[replaced]
[replaced]
ghighi

例. 上記の例の最短マッチ

$ perl -p -e "s/d.+?f/[replaced]/ig" string.txt
abcabc
[replaced][replaced]
[replaced][replaced]
ghighi

例. 上記の例でマッチした文字列を置換文字列内で使用

$ perl -p -e "s/d.+?f/[$&]/ig" string.txt
abcabc
[def][deF]
[deF][def]
ghighi

例. 上記の結果を string.txt ファイルに上書きし、元のファイルを string.old ファイルに保存する

$ perl -pi.old -e "s/d.+?f/[$&]/ig" string.txt
$ cat string.txt.old
abcabc
defdeF
deFdef
ghighi

maven-pmd-plugin(カスタムルールセットその1)

前回は既存のルールセット群から任意のものを選択しました。しかし、それよりも細かい粒度でルールを設定したいことも少なくありません。そのため、今回は既存のルールセット群の中から任意のルールをピックアップする方法を考えてみます。

以下が前回の結果のXML(basic.xml)です。

<?xml version="1.0" encoding="UTF-8"?>
<pmd version="4.2.5"
     timestamp="2011-03-23T11:31:31.015">
  <file name="C:\minimal_pmd_env\src\main\java\Hoge.java">
    <violation beginline="6"
               endline="7"
               begincolumn="19"
               endcolumn="9"
               rule="EmptyIfStmt"
               ruleset="Basic Rules"
               class="Hoge"
               method="main"
               externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#EmptyIfStmt"
               priority="3">
      Avoid empty if statements
    </violation>
    <violation beginline="6"
               endline="6"
               begincolumn="13"
               endcolumn="16"
               rule="UnconditionalIfStatement"
               ruleset="Basic Rules"
               class="Hoge"
               method="main"
               externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#UnconditionalIfStatement"
               priority="3">
      Do not use if statements that are always true or always false
    </violation>
    <violation beginline="8"
               endline="9"
               begincolumn="14"
               endcolumn="9"
               rule="EmptyIfStmt"
               ruleset="Basic Rules"
               class="Hoge"
               method="main"
               externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#EmptyIfStmt"
               priority="3">
      Avoid empty if statements
    </violation>
  </file>
</pmd>

上記から、2か所が Basic Rules の EmptyIfStmt に違反し、1か所が UnconditionalIfStatement に違反していることがわかります。

今回のゴール

今回は、以下のルールのみチェックするようなカスタムルールセットを作成してみます。

  • Basic Rules の EmptyIfStmt
  • Import Statement Rules の DuplicateImports

カスタムルールセットの作成

カスタムのルールセットを作成します。名前は何でも構いませんが、今回は MyBasicRuleSet.xml とすることにします。

<?xml version="1.0"?>
<ruleset name="Custom ruleset"
    xmlns="http://pmd.sf.net/ruleset/1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
    xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">

  <description>Sample Custom Rule Set.</description>

  <!-- Here's some rules we'll specify one at a time -->
  <rule ref="rulesets/imports.xml/DuplicateImports"/>
  <rule ref="rulesets/basic.xml/EmptyIfStmt"/>

</ruleset>

上記のように、ruleset 要素内の rule 要素に指定したいルールセットとルールを記述します。

pom.xmlの設定

 ...
<!--
  Maven PMD Plugin
    - http://maven.apache.org/plugins/maven-pmd-plugin/
    - http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-pmd-plugin/
    - http://pmd.sourceforge.net/mvn-plugin.html
  (Notice! : This must be placed after Maven JXR Plugin's definition.)
-->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <version>2.5</version>
  <configuration>
    <sourceEncoding>UTF-8</sourceEncoding>
    <rulesets>
      <ruleset>MyBasicRuleSet.xml</ruleset>
    </rulesets>
  </configuration>
</plugin>
 ...

上記のように、独自のルールセットの xml ファイルを指定します。

対象ソースコード

import java.lang.String;
import java.lang.String;

public class Hoge {
    public static void main (String[] args) {
        if (true) {
        }
        else {
        }
    }
}

実行結果

意図通り、以下のルールが適用された結果が pmd.xml に出力されました。

  • Basic Rules の EmptyIfStmt
  • Import Statement Rules の DuplicateImports

以下、pmd.xml

<?xml version="1.0" encoding="UTF-8"?>
<pmd version="4.2.5"
     timestamp="2011-03-23T12:03:41.531">
  <file name="C:\minimal_pmd_env\src\main\java\Hoge.java">
    <violation beginline="2"
               endline="2"
               begincolumn="8"
               endcolumn="23"
               rule="DuplicateImports"
               ruleset="Import Statement Rules"
               externalInfoUrl="http://pmd.sourceforge.net/rules/imports.html#DuplicateImports"
               priority="4">
      Avoid duplicate imports such as 'java.lang.String'
    </violation>
    <violation beginline="6"
               endline="7"
               begincolumn="19"
               endcolumn="9"
               rule="EmptyIfStmt"
               ruleset="Basic Rules"
               class="Hoge"
               method="main"
               externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#EmptyIfStmt"
               priority="3">
      Avoid empty if statements
    </violation>
    <violation beginline="8"
               endline="9"
               begincolumn="14"
               endcolumn="9"
               rule="EmptyIfStmt"
               ruleset="Basic Rules"
               class="Hoge"
               method="main"
               externalInfoUrl="http://pmd.sourceforge.net/rules/basic.html#EmptyIfStmt"
               priority="3">
      Avoid empty if statements
    </violation>
  </file>
</pmd>

参考

サンプル

maven-pmd-plugin(rulesetを選択してみる)

rulesets

前回の pom.xml では ruleset を特に指定していなかったので、デフォルトのものが使用されています。現在は、デフォルトの ruleset は以下のようになっています。

  • Basic Rules
    • The Basic Ruleset contains a collection of good practices which everyone should follow.
  • Import Statement Rules
    • These rules deal with different problems that can occur with a class' import statements.
  • Unused Code Rules
    • The Unused Code Ruleset contains a collection of rules that find unused code.

rulesets

rulesetを選択してみる

以下のようなファイルを PMD にかけると、Basic Rules と Import Statement Rules に抵触します。

import java.lang.String;
import java.lang.String;

public class Hoge {
    public static void main (String[] args) {
        if (true) {
        }
        else {
        }
    }
}

以下のように設定すると、Basic Rules のみを対象とするようになります。

以下、pom.xmlの変更点(rulesets要素)

<!--
  Maven PMD Plugin
    - http://maven.apache.org/plugins/maven-pmd-plugin/
    - http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-pmd-plugin/
    - http://pmd.sourceforge.net/mvn-plugin.html
  (Notice! : This must be placed after Maven JXR Plugin's definition.)
-->
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-pmd-plugin</artifactId>
  <version>2.5</version>
  <configuration>
    <sourceEncoding>UTF-8</sourceEncoding>
    <rulesets>
      <ruleset>/rulesets/basic.xml</ruleset>
    </rulesets>
  </configuration>
</plugin>

参考

サンプル

maven-pmd-plugin(最低限の設定編)

今回から、maven-site-plugin について調べてみようと思います。

最低限の設定

とりあえず、警告などが表示されないような最低限の設定を記述してみる。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <!--
    POM Reference
    - http://maven.apache.org/pom.html
  -->
  <modelVersion>4.0.0</modelVersion>

  <!--
    Maven Coordinates
    - http://maven.apache.org/pom.html#Maven_Coordinates
    - http://maven.apache.org/maven-model/maven.html#project
  -->
  <groupId>com.objectfanatics</groupId>
  <artifactId>minpmdenv</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <url>http://www.example.com/</url><!-- maven-site-plugin throws a warning if no url element detected. -->

  <!--
    Build Settings
    - http://maven.apache.org/pom.html#Build_Settings
    - http://maven.apache.org/maven-model/maven.html#build
  -->
  <build>
    <!--
      Plugins
      - http://maven.apache.org/pom.html#Plugins
      Plugin
      - http://maven.apache.org/maven-model/maven.html#class_plugin
    -->
    <plugins>
      <!--
        Maven Compiler Plugin
        - http://maven.apache.org/plugins/maven-compiler-plugin/
        - http://repo2.maven.org/maven2/org/apache/maven/plugins/maven-compiler-plugin/
      -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>

      <!--
        Maven Site Plugin
          - http://maven.apache.org/plugins/maven-site-plugin/
          - http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-site-plugin/
      -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
        <version>3.0-beta-3</version>
        <configuration>
          <inputEncoding>UTF-8</inputEncoding>
          <outputEncoding>UTF-8</outputEncoding>
          <reportPlugins>
            <!--
              Maven JXR Plugin
                - http://maven.apache.org/plugins/maven-jxr-plugin/
                - http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-jxr-plugin/
            -->
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-jxr-plugin</artifactId>
              <version>2.2</version>
              <configuration>
                <inputEncoding>UTF-8</inputEncoding>
                <outputEncoding>UTF-8</outputEncoding>
              </configuration>
            </plugin>
            
            <!--
              Maven PMD Plugin
                - http://maven.apache.org/plugins/maven-pmd-plugin/
                - http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-pmd-plugin/
                - http://pmd.sourceforge.net/
              (Notice! : This must be placed after Maven JXR Plugin's definition.)
            -->
            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-pmd-plugin</artifactId>
              <version>2.5</version>
              <configuration>
                <sourceEncoding>UTF-8</sourceEncoding>
              </configuration>
            </plugin>
          </reportPlugins>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <!-- suppress warning -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

実行結果はこんな感じ。

[INFO] Scanning for projects...
   ...
[INFO] configuring report plugin org.apache.maven.plugins:maven-jxr-plugin:2.2
[INFO] configuring report plugin org.apache.maven.plugins:maven-pmd-plugin:2.5
   ...
[INFO] Rendering site with org.apache.maven.skins:maven-default-skin:jar:1.0 skin.
[INFO] Generating "Source Xref" report    --- maven-jxr-plugin:2.2
[INFO] Generating "CPD Report" report    --- maven-pmd-plugin:2.5
[INFO] Generating "PMD Report" report    --- maven-pmd-plugin:2.5
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 5.922s
[INFO] Finished at: Tue Mar 22 22:49:46 SGT 2011
[INFO] Final Memory: 10M/28M
[INFO] ------------------------------------------------------------------------

ポイント

  1. maven 3 以降では、レポーティング系の定義には reporting 要素は使用せず、maven-site-plugin の中で定義します。
  2. maven-pmd-plugin の定義より前に maven-jxr-plugin の定義します。そうしないと、mvn site:site を実行すると1回目に失敗して2回目に成功するという状況になってしまいます。

レポート

target/site/project-reports.html として、レポートが作成されます。

参考

サンプル