2011年8月27日土曜日

MYSQLでのトランザクション処理

MYSQL 5.2 を使用してAndroidからDB操作している。

使い方は、Javaと同じで特にAndroidだから何か特別な事が必要と言う事もない。

テーブルを作成しデータを作成し、レコードへ書き込む(Insert、Update)

うまく書き込めた。


・サンプル(大体こんな感じ)

public Connection mConn = null;
// SQLサーバ ユーザー名
public static final String DATABASE_USER = "user";
// SQLサーバ パスワード
public static final String DATABASE_PASSWORD = "password";
// キャラクターコード
public static final String CHARACTER_ENC = "characterEncoding";




Class<?> driverClass = Class.forName("com.mysql.jdbc.Driver");
// サーバーマシンのIPアドレスを設定
// ローカルにMySQLがある場合、10.0.2.2 を指定
String strCon = "jdbc:mysql://192.168.100.100:3306/test_tbl?useUnicode=true";

Driver driver = (Driver)driverClass.newInstance();
Properties prpt = new Properties();
prpt.put(DATABASE_USER, "root");
prpt.put(DATABASE_PASSWORD, "123");
prpt.put(CHARACTER_ENC, "utf8");

mConn = driver.connect(strCon, prpt);
// オートコミットの解除(トランザクション制御がしたい為)
mConn.setAutoCommit(false);

Statement stmt = _conDB.mConn.createStatement();
stmt.executeUpdate("UPDATE persondata SET age=10");


しかし、後で気づいた。

mConn.setAutoCommit(false);これ、やってるんだから更新されてはいけない。

更新する為には明示的にCommitが必要のはず。

Commitの前にExceptionが出たらRollbakしないといけない。

Exceptionになったら、Rollbakするように記述してみた。

mConn.rollback();

executeUpdateした後、わざとExceptionを発生させロールバックしてみるも、正常に更新されてしまう。

調査して分かった事。

テーブル作成時のストレージエンジンの種類を全部「MyISAM」で作成していた。

「MyISAM」はトランザクション処理をサポートしていない。

トランザクション制御するなら有名な「InnoDB」がセオリーか。

なので、テーブルを全部「InnoDB」にしようと思ったが、それぞれ特徴があるので良く考えて変えるべき。

「MyISAM」はスピードが速いので更新しないSelectしかしない様なテーブルや更新が少ないテーブル(マスター系等)に使う。
「InnoDB」はトランザクション処理に対応しているので更新系(明細系)のテーブルに使う。


「MyISAM」はテーブルロックする
「InnoDB」はレコードロックする


まぁ、主流が「InnoDB」なので例外的に「MyISAM」を使用する機会がなければ全部「InnoDB」でもいいと思う。


とりあえず、コミットとロールバックは出来るようになって解決。

 
   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年8月26日金曜日

eclipseのAndroidデザイナ

eclipseで使用できるAndroidのvisualなデザイナがある。

フォルダ的には"\res\layout"にあるファイルが対象になる。

レイアウトファイルをパッケージエクスプローラー等からダブルクリックすると、「Graphical Layout」と言うタブで、レイアウトデザイナが起動する。

Android[2.1]や[2.2]、[2.3]向けに作成している時に、デザインがくずれてうまく表示されない。

デザイナ上ではくずれるが、実行するとうまく表示される。

そこで、2.1向けだとしてもデザイナの対象バージョンを3.2にしてやる。












そうすると、ほとんどのデザインバグが直る。

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月30日土曜日

開発環境バージョンアップ

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT 12.0.0.v201106281929-138431
JavaSDK 1.6.0_24
AndroidSDK_r12


開発環境のバージョンアップをした。

「AndroidSDK_r11」から「AndroidSDK_r12」へ。

それに伴い「ADT 11.なんとか」から「ADT 12.0.0.v201106281929-138431」へ。

その後、再起動しエミュレータを起動しようとしたら以下のメッセージが出て起動せず。

> invalid command-line parameter: s.
> Hint: use '@foo' to launch a virtual device named 'foo'.
> please use -help for more information

原因がさっぱり分からず。

調査した所、元々インストールしてあったパスに半角スペースが含まれているのが原因かも。

確かに、「C:\Program Files\Android-r11\」にインストールしてあった。

「D:Android-r12」に変更し、環境変数のパスを変更してみたらうまく動いた。
 

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月26日火曜日

続・フリック

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
媒体 = エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


フリックした時に特定のオブジェクト(部品)だけ反応して欲しい。

しかし、今の作りだとどこを押しても「onTouchEvent」が走ってしまう。


private GestureDetector mDetector;

public void onCreate(Bundle savedInstanceState) {
    mDetector = new GestureDetector(MyActivity.this, MyActivity.this);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    super.onTouchEvent(event);
    mDetector.onTouchEvent(event);
    return true;
}

@Override
public boolean onFling(MotionEvent e0, MotionEvent e1,
                        float velocityX, float velocityY)
{
    // 右方向へフリック
    if (e0.getX() < e1.getX()) {
        // 処理
    }
}


タッチした対象オブジェクトを知りたい場合どうすればいいのか。

そもそも、フリックは「GestureDetector」と「onTouchEvent」と「onFling」を使っているが、これを使い続けた場合タッチされたオブジェクトの特定は出来ないかもしれない。

そこで、オブジェクトごとにタッチイベントを捕らえる事にした。


public class MyActivity extends Activity implements OnTouchListener{

    private TextView mTvView;
    private GestureDetector mDetector;

    public void onCreate(Bundle savedInstanceState) {
        mTvView = (TextView)findViewById(R.id.tvMenu);
        // クリックリスナー登録
        mTvView.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // 処理
        return mDetector.onTouchEvent(event);
    }

    @Override
    public boolean onFling(MotionEvent e0, MotionEvent e1,
                            float velocityX, float velocityY)
    {
        // 右方向へフリック
        if (e0.getX() < e1.getX()) {
            // 処理
        }
    }
}


「onTouch」の引数にViewが渡ってくるし、フリックしたいオブジェクトだけ「setOnTouchListener」すればいい。

これで「onFling」を引き続き使えると思っていたら、ScrollViewに対してはタッチイベントは来る物の、フリックイベントは走らない。

原因不明。

なので、「onFling」は使うのをやめて「onTouch」で泥臭いコードを書く事にする。


private float lastTouchX;
private float currentX;

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {

    case MotionEvent.ACTION_DOWN:
        lastTouchX = event.getX();
        break;

    case MotionEvent.ACTION_UP:
        currentX = event.getX();
        if (lastTouchX < currentX) {
            //前に戻る動作
        }
        if (lastTouchX > currentX) {
            //次に移動する動作
        }
        break;

    case MotionEvent.ACTION_CANCEL:
        currentX = event.getX();
        if (lastTouchX < currentX) {
             //前に戻る動作
        }
        if (lastTouchX > currentX) {
             //次に移動する動作
        }
        break;
    }
    return false;
}

ちなみに、 event.getX()は相対座標が帰ってくる。

部品の上でタッチしたらその部品の座標が帰ってくる。
ボタンの上でタッチしたらボタンのX座標が帰ってくるが、押したまま移動(MOVE)させるとボタンから指がはずれて、スクリーン全体の座標が取れるようになる。

タッチダウン → ムーブ で指を動かしている最中に突然、おかしな値が取れるように見える。

タッチした部品の座標ではなく、常にスクリーンの絶対座標が取得したい場合は、event.getRawX()」で取得できる。
 

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月25日月曜日

Androidプロジェクト作成時のビルド・ターゲット

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11


いつも使っているワークスペースの使用を一旦やめた。

新規にフォルダを作成し、そこを新しいワークスペースにした。

Androidプロジェクトを新規作成した。

クラス名やパッケージ名を入れるが、ビルド・ターゲットには何もでない。

エミュレータデバイスは作成済み。

調べた結果、eclipseのAndroid設定の「SDK ロケーション」の設定が間違っているか設定されてないのでは?との事。

確認してみたら、確かに空白になっていた。

さっきまで入っていたのに。

いつも使っているワークスペースから他のスペースに移動したから?

結局、Androidに限らずEclipseの仕様と思う。


   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月24日日曜日

findViewByIdでnullが返る

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
媒体 = エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


nullが返るソース。

・aaa.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">
    <LinearLayout
        android:id="@+id/linLay"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </LinearLayout>
</LinearLayout>


・bbb.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">
    <TableLayout
        android:id="@+id/tblLay" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </TableLayout>
</LinearLayout>


MainActivity.java(修正前)
public class MainActivity extends Activity{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aaa); ← ここに注目(aaa.xmlを設定)
 
        // 正常な値が返ってくる(aaa.xml内のidから取得)
        LinearLayout LinLay = (LinearLayout)findViewById(R.id.linLay);
        // nullが返ってくる(bbb.xml内のidから取得)
        TableLayout TabLay = (TableLayout)findViewById(R.id.tblLay);
    }
}


自分自身のレイアウトは「aaa.xml」になっている。

setContentView(R.layout.aaa);
これで決定する。

findViewByIdで現在設定されていない他のレイアウトからオブジェクトを取得しようとしても、普通に取得しようとしてもnullが返ってくる。

いくつか方法があるが、今回は「LayoutInflater」を使う。


MainActivity.java(修正後)
public class MainActivity extends Activity{
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.aaa); ← ここに注目(aaa.xmlを設定)

        // 正常な値が返ってくる(aaa.xml内のidから取得)
        LinearLayout LinLay = (LinearLayout)findViewById(R.id.linLay);

        // レイアウトインフレーター使用
        LayoutInflater factory = LayoutInflater.from(this);
        // 他のレイアウトファイルを指定
        View layInfView = factory.inflate(R.layout.bbb, null);

        // 正常な値が返ってくる(bbb.xml内のidから取得)
        TableLayout TabLay = (TableLayout)layInfView.findViewById(R.id.tblLay);
    }
}

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月22日金曜日

Layout関連のClassCastException

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
媒体 = エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


現象:
アプリ起動時にExceptionが発生し起動しない

内容は以下


java.lang.RuntimeException: Unable to start activity ComponentInfo{jp.test/jp.test.CTestActivity}: java.lang.ClassCastException: android.widget.TextView
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)





Caused by: java.lang.ClassCastException: android.widget.TextView
    at jp.test.CTestActivity.onCreate(CTestActivity.java:93)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)


ExceptionはレイアウトファイルのIDを取得しようとすると発生


レイアウトファイルの記述は以下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:id="@+id/linearLayout01"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_weight="1.9">
        <GridView
            android:id="@+id/gridView1"
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:numColumns="1">
        </GridView>
    </LinearLayout>

    <View
        android:id="@+id/Separator01"
        android:layout_width="wrap_content"
        android:background="#FFFFFF"
        android:layout_height="1dp"
        android:layout_marginBottom="2dp">
    </View>

    <LinearLayout
        android:id="@+id/linearLayout02"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
        <Button
            android:text="注文完了"
            android:id="@+id/btnDone"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:text="キャンセル"
            android:id="@+id/btnCancel"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button
            android:text="ダミー"
            android:id="@+id/btnDamy"
            android:layout_weight="1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>

    <View android:id="@+id/Separator02"
        android:layout_height="1dp"
        android:layout_width="wrap_content"
        android:background="#FFFFFF"
        android:layout_marginBottom="2dp">
    </View>

    <LinearLayout
        android:id="@+id/linearLayout03"
        android:orientation="vertical"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent">
    </LinearLayout>

    <View
        android:id="@+id/Separator03"
        android:layout_width="wrap_content"
        android:background="#FFFFFF"
        android:layout_height="1dp"
        android:layout_marginBottom="2dp">
    </View>

    <ScrollView
        android:id="@+id/svMenu"
        android:layout_height="wrap_content"
        android:layout_width="fill_parent"
        android:layout_weight="1">
        <TableLayout
            android:id="@+id/tlMenu"
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:layout_weight="1">
        </TableLayout>
    </ScrollView>

</LinearLayout>
 

ソースは以下


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

    mLinearLayout01 = (LinearLayout)findViewById(R.id.linearLayout01);
    mLinearLayout02 = (LinearLayout)findViewById(R.id.linearLayout02);
    mLinearLayout03 = (LinearLayout)findViewById(R.id.linearLayout03);
}

Exceptionは「findViewById(R.id.linearLayout03)」を実行すると発生。

id名が間違っているわけでもない。

レイアウトファイル側は「LinearLayout」として作ってあるのでキャストも「LinearLayout」にしている。
01と02がうまく行っているのに03だけうまくいかない。

エラー行はコメントアウトし、03を分解してみた。


Object aaa = findViewById(R.id.linearLayout03);
mLinearLayout03 = (LinearLayout)aaa;


ワンクッション置いただけ。ステップ実行したがうまくいく。

エラー行と同じ記述で新規にもう一行作る。


//mLinearLayout03 = (LinearLayout)findViewById(R.id.linearLayout03);
Object aaa = findViewById(R.id.linearLayout03);
mLinearLayout03 = (LinearLayout)aaa;
mLinearLayout03 = (LinearLayout)findViewById(R.id.linearLayout03);


うまくいく。

エラー行にごみデータでもあったのか。

eclipseかAndroidのバグなのか。

原因不明。

 
   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月20日水曜日

ダイアログ表示で、Window Leaked(メモリリーク)

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
媒体 = エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


普通にダイアログを表示しようとした所、Exception「Window Leaked」と言われた。


・最初に書いたコード

@Override
public void onCreate(Bundle savedInstanceState) {
    // 表示項目の配列
    final String[] colors = { "RED", "BLUE", "YELLOW" };
    // タイトルを設定
    alertDialogBuilder.setTitle("タイトル");
    // 表示項目とリスナの設定
    alertDialogBuilder.setItems(colors,
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // 項目が選択されたときの処理
            }
        }
    );

    // ダイアログを表示
    alertDialogBuilder.create().show();
}


調べたらライフサイクルの管理の問題の可能性が高い事が分かった。

上記の方法はライフサイクルを自前で管理する方法。

Android側に管理させる方法を取らないと難しいかもしれない。


・Android側に管理させる方法

@Override
public void onCreate(Bundle savedInstanceState) {
    // 引数は何でもいい。onCreateDialogメソッドに渡っていくだけ。
    showDialog(0);
}

@Override
protected Dialog onCreateDialog(int id) {
    return createDialog(id);
}

/**
 * ダイアログ生成
 * @param id
 * @return
 */
private Dialog createDialog(int id) {
    if (id == DIALOG_ID_ABESHI) {
        // 表示項目の配列
        final String[] colors = { "RED", "BLUE", "YELLOW" };
        // タイトルを設定
        alertDialogBuilder.setTitle("タイトル");
        // 表示項目とリスナの設定
        alertDialogBuilder.setItems(colors,
            new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    // 項目が選択されたときの処理
                }
            }
        );

        return alertDialogBuilder.create();
    }
    return null;
}


まず「showDialog」メソッドを実行する。

すると、ダイアログ作成イベントが走り、onCreateDialog」が実行される。

こうする事でAndroid側に管理させる事になるようだ。

   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月19日火曜日

引数=値渡しと参照渡し

Java全般の話。

通常、Javaのメソッド引数は値だけが渡される。


void aaa(){
    String strDamy="000";
    bbb(strDamy);
    System.out.println("strDamy = " + strDamy);
}

void bbb(String _str){
    _str="123";
}


こんなコードを書いてもメソッドの呼び元ではStringの値は変わらない。

表示されるのは「000」のはず。

C言語だと「ポインタ」を使うし、VBなら「ByRef」を使う

Javaはどうするか。

コレクション等でラップしてやる。


void aaa(){
    String strDamy="000";
    ArrayList arrDamy = new ArrayList();
    arrDamy.add(strDamy);
    bbb(arrDamy);
    strDamy = (String)arrDamy.get(0);
    System.out.println("strDamy = " + strDamy);
}

void bbb(ArrayList _arr){
    String str="";
    str=(String)_arr.get(0);
    _str="123";
    _arr.clear();
    _arr.add(str);
}

初歩的な事だけど、知らずに苦労した。

通常は返値をvoidからStringにしてreturnすれば事たりる。

しかし、すでに返値が使用されている場合、しょうがなく引数で返さないといけない場面も出てこよう。

返値をArrayListにして全部突っ込めばいいんじゃないかと言う話もある。

その辺は設計しだいなので各自の判断で。

そして、この方法がベストかと言うと分からない。

いくつかある方法の一つなのかもしれない。

知ってる人は教えて下さい。

-----------------
2011/07/20 追記:
-----------------
コメントで「StringBuffer」を使うと楽になるとの事なので、修正コードを転記する。

void aaa(){
     StringBuffer strDamy = new StringBuffer("000");
     bbb(strDamy);
     System.out.println("strDamy = " + strDamy);
}

void bbb(StringBuffer _str){
     _str.setLength(0);
     _str.append("123");
}

String型は良く使うのでStringBufferで代用すると言うのはかなり有益だ。

話は変わり、この記事で言いたかった事は、オブジェクト内の値の受け渡しについて。

実際にあった話として
CConnectDB conDB; // DB接続用のオブジェクト
Statement st;         // DB操作用のオブジェクト

conDB」や「st」を引数に渡して、その先のメソッドで値を変えても戻ってきたら何も変わってなかった。困った。
なので、String型やその他の変数やオブジェクトで代用が効く方法があればいいが、通常はやはりArrayなどのコレクションに入れて渡すのが手っ取り早いと思われ。

できればスッキリした分かり易いコードを書きたいが・・・


   ↓クリックで、このブログの評価が上がり執筆者が喜びます
 にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月15日金曜日

フリック

開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
テスト媒体:エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


フリック=指を画面にタッチして上下左右、どっちかにタッチしたまま動かし指を離す
これをすばやく行う


・フリックの実装

// タッチダウン、移動、タッチアップを全部自分で計算してやる方法もあるがめんどくさい
// Gesture系のオブジェクトがあるのでそれを使って実装
private GestureDetector mDetector;

// ジェスチャー検出クラス(フリック等)
public class TestActivity extends Activity implements GestureDetector.OnGestureListener {

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




        // ジェスチャーオブジェクトの生成
        mDetector = new GestureDetector(this, this);
    }

    /**
    * @param e0 指を置いた時の位置
    * @param e1 現在の位置
    * @param velocityX X軸の移動距離
    * @param velocityY Y軸の移動距離
    */
    // フリックを司るメソッド
    @Override
    public boolean onFling(MotionEvent e0, MotionEvent e1,
                            float velocityX, float velocityY)
    {
        // ここにフリック時の実装をする
        if (e0.getX() < e1.getX()) {
            // 右へフリック(指をタッチした後、右へ動かす)
        } else {
            // 左へフリック(指をタッチした後、左へ動かす)
        }
        // getY() で上下に対応
    }

    /* (非 Javadoc)
     * 背景画面でもボタンの上でもどこでもタッチイベントが取れる万能メソッド
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        super.dispatchTouchEvent(event);
        mDetector.onTouchEvent(event);
        return onTouchEvent(event);
    }
}

「onTouchEvent」メソッドもあるが、これは条件によってはイベントが走らない。

なので常にどこをタッチしてもイベントが走る「dispatchTouchEvent」を使用する。


    ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年7月14日木曜日

MySQLサーバーへの生死確認(タイムアウト値の設定)

サーバー環境:
アプリケーションサーバー:アパッチ
SQLサーバー:MySQL 5.1
↑これはXamppを導入したもの


開発環境:
Windows Vista Home
eclipse 3.5(ガリレオ)
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r11
開発・ターゲットVer=Android2.1


テスト環境:
テスト媒体:エミュレータ
↑SDK ManagerでVer2.1のHVGAで作成


事前準備:
プロジェクトフォルダに「libs」と言う名前のフォルダを作成した
そこに、MySQLコネクタjarファイルを入れる
eclipse上からプロジェクトのプロパティで上記のビルドパスを通した
その時、「外部JARの追加」ではなく「JARの追加」で行った


今回はマシンの構成とかサーバー構成とかは関係ない。

MySQLサーバーに接続しようとしたらサーバの電源が入ってなく、接続結果の応答も30秒位ない。

これでは、長すぎるので自分でタイムアウトを設定したい。


・最初に書いてあったコード

import java.sql.*;

Class.forName("com.mysql.jdbc.Driver");
String url = String strCon = "jdbc:mysql://192.168.0.1:3306/pos_manage";
Connection con = DriverManager.getConnection(url);
Statement stmt = con.createStatement();

これがタイムアウトするまでにかなり待たされる。

これで調べたら、「DriverManager.setLoginTimeout(seconds)」と言うのがあったので設定してみたが、変わらず。

さらに調べた結果、「DriverManager」を使うのが良くないとの事。


・次にに書いたコード

Class driverClass = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver)driverClass.newInstance();
Properties prpt = new Properties();
prpt.put("user", "root");
prpt.put("password", "123");
prpt.put("connectTimeout", "10000");//多分DBサーバーへの接続タイムアウト
prpt.put("socketTimeout", "10000"); //多分ネットワークタイムアウト
prpt.put("autoReconnect", "false"); //タイムアウトしたら再接続するか
conn = driver.connect(strCon, prpt);

こんな感じでやれと、ネットに書いてあったがやはりダメ。

まずはサーバーの電源が入ってない事による通信タイムアウトを設定したい。

上記のコードはあくまでもSQLオブジェクト。

電源が入ってても何らかの原因で通信できなくなった時の事も含まれる。

そこで考えたのが、単純にサーバーが通信できる状態にあるかどうかだけ確認する。


・最終コード

// テスト用のURLを作成
//XamppにはApatchが入っててMySQLと一緒に起動している前提
URL urlTest = new URL("http://192.168.0.1");
// MySQLサーバー接続用オブジェクトの作成
URLConnection connection =  (HttpURLConnection)urlTest.openConnection();
// タイムアウト値の設定
connection.setReadTimeout(5000);
connection.setConnectTimeout(5000);
// 接続開始
// タイムアウトになったらExceptionが発生する
connection.connect();


通信できる状態なのかの確認だけならこれでOK

 

  ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
  にほんブログ村

2011年4月11日月曜日

アプリ公開準備+AndroidMapの公開用キー取得

環境:
WindowsXP SP3
eclipse3.5
ADT_今日の時点で最新の物(バージョン不明)
JavaSDK 1.6.0_24
AndroidSDK_r09

開発・ターゲットVer=Android2.1

実機=au IS01(シャープ製)



やった事。
エミュレータと実機での動作。2.1として開発したがマニフェストをいじって1.6から動作対称にしたので動作するか確認。リリース用に実機動作の仕方が分からなかった。



エミュレータと実機での動作
AndroidMapKey デバイス       証明書
デバッグ用    エミュレータ(v2.1)  eclipseから実行(デバッグ)
デバッグ用    エミュレータ(v1.6)  eclipseから実行(デバッグ)
デバッグ用    実機         eclipseから実行(デバッグ)



アプリをリリースモードで作成する必要がある。

通常デバッグ用の証明書になっているが公開用の証明書を作る。


1、eclipse上でパッケージエクスプローラ等のプロジェクト名を右クリック









2、Android Toolを選択。サブメニューから「Export Signed Application Package」を選択










3、まずは公開用証明書の作成
  ロケーションに証明書ファイルを保存したい場所を入力
  パスワードは忘れないように














4、公開用証明書入りのアプリケーションファイル(*.apk)の作成
  エイリアスは証明書の省略名、パスワードはさっき作った公開用証明書のパスワード、Varidityは何年有効にするか。Googleは25年以上の公開を規定しているので30年後まで有効にでもしておけばいいかも


これで、証明書とアプリができる。

Androidマーケットに、このアプリ(apk)をアップロードすればマーケットへの公開完了だが、Mapを使うとなるとリリース用のMapKeyがいる。


コマンドプロンプトから以下を入力
keytool -list -keystore "(Androidのリリース用keysoreファイル)"

後はデバッグ用に作ったMapKey申請と同じ。

表示されたフィンガープリントを使って「http://code.google.com/intl/ja/android/add-ons/google-apis/maps-api-signup.html」ここで申請する。

多分これでMapアプリをマーケットに公開できるはず。


[追記]
マーケットへの公開前に実機で確認しようとしたがMAPが表示されない。

リリース用の証明書を作成し、公開用のMAPキーも取得した。
デバッグ用の証明書、公開用のMAPキーだとMAPが表示される(eclipseから実行)

要追跡調査。











調査結果。凡ミス。
res/values/string.xml
ここに"map_key"をデバッグ用、リリース用と作り、用途により分けるようにした。

しかし
res/layout/main.xml
ここでstring.xmlに登録したmap_keyを使っていると思ったら、使ってなかった。
ベタでデバッグ用のMapKeyを書いていたので「@string/map_key」に書き換えた。

すんなり動いた。
真っ白なマップしか表示されてなかったが、きちんとMAPが表示されるようになった。



   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年4月7日木曜日

Androidアプリ、実機テスト

実機でテストしようとしたが、eclipseのデバッグ実行時のデバイス選択一覧に実機が出てこない。   

USBドライバのインストール自体がうまくいってない様子。

実機はauの「シャープ IS01」


解決方法:
1、Android側でデバッグ実行できるように2つ程、設定を変更した。


2、シャープのサイトへ行き「IS01用のUSBドライバ」をダウン&インスト
https://sh-dev.sharp.co.jp/android/modules/driver/list.php


3、またシャープのサイトで「シャープ共通adb USBドライバー」をダウンロード&展開
https://sh-dev.sharp.co.jp/android/modules/driver/
シャープ製Androidほぼ全機に対応


4、Androidをパソコンに接続


5、ドライバのインストを促されるので「シャープ共通adb USBドライバー」を指定する


これで、ドライバ類のインストールはうまくいった。
5番目がうまくいってなかったが、「シャープ共通adb USBドライバー」があるとは知らなかった。他のサイトで「Android-sdk_r09-windows\extras\google\usb_driver」ここにある「android_winusb.inf」にIS01の記述を追加すると書いてあったが、やってもだめだった。

後は「adb devices」コマンドで実機が接続されているのを確認して、あればOK。
なければ、マシンを再起動したほうがいいかも。

このコマンドで実機が見つからなければ、当然eclipseで実機デバッグ実行もできない。





↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年3月29日火曜日

eclipseのXMLデザイナーが開かない

eclipse(プレアデス)開発でAndroidのXMLレイアウトについて。

main.xmlをデザイナーモード(Graphical Layout)で開こうとしたらエラーが出た。

「エラーが発生しました。詳細については、エラー・ログを参照してください。」
「com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationComposite.(Lcom/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite$IConfigListener;[[Lcom/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite$CustomButton;Lorg/eclipse/swt/widgets/Composite;ILjava/lang/String;)V」

これは、ADT-Pluginのアップデートをすると起こるらしい。
ADT 9.0.0と10.0.0で再現確認。

解決方法:
1、eclipseを終わらせる

2、clearnバッチで起動させる

3、main.xmlをデザイナーモード(Graphical Layout)で開く

4、この段階では表示されないかもしれない。表示されなければ上にあるAndroid対象バージョンを、正しいバージョンに変えてやる。

5、しばらく待つ

6、表示された


参考URL:
http://www.hlplus.jp/php/blog/index.php?UID=1296543897
http://www.hlplus.jp/php/blog/index.php?UID=1298450960



  ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年3月23日水曜日

XOOPS 構築 ホダ塾ディストリビューション

テスト環境はXAMPP。

インストールは、適当なサイトに書いてあるとおりでいい。

インストの途中で「XOOPS_TRUST_PATH」を設定する画面が出る。

ここに「http://localhost/myPage/xoops_trust_path」と入力してエラーになっていた。

エラー内容は

「Warning: require(/home/balisurf/xoops_trust_path/modules/protector/include/precheck.inc.php) [function.require]: failed to open stream: No such file or directory in /home/balisurf/public/www/mainfile.php on line 105」

「Fatal error: require() [function.require]: Failed opening required 」

ファイルが読み込めないと言っている。

原因は、

1:ファイルがない
2:フォルダがない
3:パスが間違っている


のどれか。


フォルダもファイルもあるので、パスが間違っている。
1時間ほど検索調査&試行錯誤して、凡ミスに気づく。

"URLじゃなくローカルの相対パスか絶対パスを入力する"

「C:¥xampp¥htdocs¥myPage¥xoops_trust_path」

これで、解決した。

しかし、本番サーバーにアップした場合はパスが変わってくるので注意。


   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年3月17日木曜日

地図表示とGPSで自分の位置を表示する

参考にしたブログで使われていたAndroidバージョンが古いのかVer2.2ではコンパイルエラーが出て使えなかった。
なので、修正した。

環境:Google APIs Ver8(Android 2.2)
          eclipse(ver3.5)
          エミュレータ


以下、修正ソース

public class IamHere extends MapActivity {
    private MapView mapView;

    /** Called when the activity is first created. */
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);

        // マップを制御するために、マップビューとコントローラを生成する
        mapView = new MapView(this, getResources().getString(R.string.map_key));

        // Activityを有効にする
        mapView.setEnabled(true);
        // クリックできるようにする
        mapView.setClickable(true);
        // ズーム機能を使えるようにする
        mapView.setBuiltInZoomControls(true);

        setContentView(mapView);
        // テストのエミュレータ用(初期化=東京駅に設定)
        Double ido = 0.0;
        Double keido = 0.0;
        ido = 35.681382 * 1E6;
        keido = 139.766084 * 1E6;
        MapController mapController = this.mapView.getController();
        mapController.setCenter(new GeoPoint(ido.intValue(), keido.intValue()));
        mapController.setZoom(7);
    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    // メニューボタンが押下されたときの処理
    // メニューにアイテムを追加する
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      boolean supRetVal = super.onCreateOptionsMenu(menu);
      menu.add(0, 0, 0, "今ここにいます");

      return supRetVal;
    }

    // メニューのアイテムが選択された時の処理
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

       Double ido = 0.0;
       Double keido = 0.0;

       switch (item.getItemId()) {
           case 0:
            // 自分の居る位置(緯度、経度)を取得する
            LocationManager locationManager = (LocationManager)this.getSystemService(Context.LOCATION_SERVICE);
            Location location =
                locationManager.getLastKnownLocation(
                        LocationManager.GPS_PROVIDER
            );

// 実機用
//            ido = location.getLatitude() * 1E6;
//            keido = location.getLongitude() * 1E6;


            // テストのエミュレータ用
            ido = 99.180192510714434 * 1E6;
            keido = 999.876859664917 * 1E6;
      (緯度、経度はでたらめ)

            MapController mapController = this.mapView.getController();
            mapController.animateTo(new GeoPoint(ido.intValue(), keido.intValue()));
            return true;
       }

       return false;
    }
}


1、実行すると地図が出る
2、画面タッチでズームイン、ズームアウトできる
3、メニューから「今ここにいます」を選ぶ(それしか出ない)
4、自分のいる位置が拡大表示される


次回は、自分の位置にマーカーをセットしたい


・参考URL
http://blog.goo.ne.jp/android99_2007/e/eda2ffce3464fa9b3181f0812c3e8e0c
http://android-go.seesaa.net/article/123033515.html


 
   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ
   にほんブログ村

2011年3月15日火曜日

「Google Map(Android Mapと言うらしい)」真っ白な画面しか出ない原因が分かった

まず、デバッグで実行するにしても実機でやるにしても「Google MAPS APIのキー」が必要。
 
   ↓クリックで、このブログの評価が上がり執筆者が喜びます
にほんブログ村 IT技術ブログ プログラム・プログラマーへ



■キーの取得方法(デバッグ編)
1、コマンドプロンプトを使う。インストールしたJavaのbinフォルダにパスを通すか、そこの場所まで移動する。

2、「keytool」と言うexeを使用する。

3、「Documents and Settings\ユーザー名\.android」にdebug.keystoreがあるのでそれをkeytoolの引数に指定する。
例)keytool -list -keystore "C:\Documents and Settings\安藤ロイド\debug.keystore"

以下のようにパスワードを聞かれるが、入れなくていいのでEnter押下。
「キーストアのパスワードを入力してください:」→このままEnter
*****************  警告 警告 警告  *****************
*  キーストアに保存された情報の完全性は検証されて  *
*  いません!  完全性を検証するには、キーストアの   *
*  パスワードを入力する必要があります。            *
*****************  警告 警告 警告  *****************
キーストアのタイプ: JKSキーストアのプロバイダ: SUN
キーストアには 1 エントリが含まれます。
androiddebugkey, 2009/05/24, PrivateKeyEntry,
証明書のフィンガープリント (MD5): 99:CF:99:AB:D9:29:FD:99:02:7B:15:4E:48:99:DD:99
(このフィンガープリントはでたらめ)

フィンガープリントをどっかにコピペしておく。

4、http://code.google.com/intl/ja/android/maps-api-signup.html にアクセス。
  下にチェックし、さっきのフィンガープリントをペーストして「Generate API Key」ボタンを押下。
  以下のような画面が出る。上の方に長いキーがあるのでコピペして保存しておく。


















■コーディング方法
リソースの「main.xml」で画面を構築してついでに、そこへAPIキーを埋め込む方法と、ほとんどJavaコードだけで記述する方法があるが、楽なのでJavaコードだけでコーディングする。

string.xml位は設定する。さっきのAPIキーを登録。
<string name="map_key">XXij5yXhQoQkDVFb6AqlyXXPyLOOivXXapjS4XX</string>
(このキーはでたらめ)

これをせずに実行していた為、マップが出ずに真っ白な画面の下にGoogleMapとだけ出ていた。間違えて画面のタイトルを入れていた。


ぶっちゃけAndroidのマニュアルは見てない。ついカッとなってやった。反省はしていない。

マニュアル?何それ?おいしいの?


ファイル名:
IamHere.java

パッケージ名:
package com.google.android.iamhere;


・以下、ソースコード全文

package com.google.android.iamhere;

import com.google.android.maps.MapView;
import android.os.Bundle;

(普通のActivityではない)
public class IamHere extends MapActivity {
    private MapView mapView;
    /** Called when the activity is first created. */
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        // マップを制御するために、マップビューとコントローラを生成する
        mapView = new MapView(this, getResources().getString(R.string.map_key));
        // Activityを有効にする
        mapView.setEnabled(true);
        // クリックできるようにする
        mapView.setClickable(true);
        // ズーム機能を使えるようにする
        mapView.setBuiltInZoomControls(true);
        setContentView(mapView);
    }
    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }
}

プロジェクトはいつものAndroidエミュ(Ver2.2)ではなく、GoogleAPI(Ver8)を指定する
あらかじめGoogleAPIの使用したいバージョンをSDK Managerでインストールしておく。
デバッグ構成にGoogle API(v8)を指定して実行。















次回はGPS機能を使用したい。