2011年3月29日火曜日

近況

就職活動のためあまりいじれていない現状です。
いつのまにか2000hitこえてた・・・!
終わったらぼちぼち再開していこうと思っています。

2011年2月15日火曜日

androidのファイル入出力、Intentについて

ファイル出力
context.openFileOutput(sFileName,Context.MODE_PRIVATE);
第一引数はファイル名で第二引数はアクセスの種類 自身のアクセスのみか外部からのアクセスを許可するかなどを設定できる

ファイル入力
context.openFileInput(sFileName);
第一引数はファイル名
アンドロイドはアプリごとに固有のフォルダを作成しているのでそのフォルダのファイルを扱う場合はフルパスの必要がない。SDカードの場合などはフルパスの必要有り

このファイル入出力をひとつのクラスで管理しようとしてはまってしまった
openFileOutputはcontextのパブリックメソッドかーとリファレンス読んで理解
じゃあcontext継承して入出力管理すりゃいいかと何故か考えてしまった・・・
継承したクラスからopenFileInputとか読んでもnullPointerの例外が
この継承したクラスはアプリ情報持ってないですし無理なの当たり前と気付くのに2時間
なにやってんだろ・・・

つまり入出力管理するにはアプリ情報が必要なのでを他クラスで入出力管理する場合はContextを渡してからファイル処理する必要があるということです。
それでクラスのコンストラクタにContextを渡して処理することにより解決
この渡してもらったContextからopenFileInputなどすればOK

もうひとつIntentのPutExtraについて
intentで値を渡す場合はputExtra("name",value)という感じにする
様々な型のオーバーロードが用意されている

毎回値を変えていく設計をしたときにはまった
putExtra("name",value)のvalueが呼ばれるたびに値が変わっていく仕様でコーディングしていたときに
値が初回のputExtraから更新されないということに。


PendingIntent contentIntent01 = PendingIntent.getActivity(this0, intent01, 0);  
intentからpendingIntentを作成する際のgetActivitiyに問題があった。
第四引数が情報の更新をするかどうかのフラグなんだがよく調べずに0入れていた
ここをPendingIntent.FLAG_UPDATE_CURRENTに変えると更新されるように。

こっちはぐぐったら同じようなことにはまっている人がいてた
その人も書いてたけどよく調べてから実装しようと。
心がけます・・・

2011年1月20日木曜日

PCとAndroidの通信(BlueTooth)がわからん

AndroidHackなど読みつつやってみたが。。。

TeraTermにてBlueToothで使用している仮想シリアルポートを指定して通信をはじめるとしっかりデータのやりとりはできている。

しかし.NETFrameworkとC#で作った簡単なシリアル通信プログラムだとなぜかデータが受信しない
1回だけデータを受け取ったことはあるがそれっきり受け取らない・・・
よーわからん!

2011年1月3日月曜日

android.widget.Buttonの座標を設定する方法2

前回absoluteLayoutを使って実装したものを紹介したのですがもっと簡単なやつありました。

void android.view.View.layout(int l, int t, int r, int b)
Viewに対してleft,top,right,bottomを指定できます。
これなら他のLayoutでも可能っぽい。
試しにLinearLayoutで作ってみました。


import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.Button;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;

/**
 * レイアウトの配置の仕方のテスト クリック、タッチ、ロングタッチイベントの呼び出し順序確認
 *
 * @author kuro
 */
public class AndroidFormTest extends Activity implements OnClickListener,
  OnLongClickListener, OnTouchListener {
 private Button button1;
 private int mState = 0;
 private int offsetX = 0;// ボタンクリックしたスクリーンのX座標とボタンのX座標の差分
 private int offsetY = 0;// ボタンクリックしたスクリーンのY座標とボタンのY座標の差分
 private final int STATE_NONE = 0;
 private final int STATE_DRAG = 1;
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  //setContentView(R.layout.main);
  LinearLayout linearLayout = new LinearLayout(this);
  setContentView(linearLayout);
  //ボタン作成
  button1 = new Button(this);
  // 各イベントリスナの登録
  button1.setOnClickListener(this);
  button1.setOnLongClickListener(this);
  button1.setOnTouchListener(this);
  linearLayout.addView(button1, new LinearLayout.LayoutParams(150,50));
  button1.setText(button1.getLeft() + "," + button1.getTop());
 }
 @Override
 public void onClick(View v) {
  // TODO 自動生成されたメソッド・スタブ
  button1.setText("onClick");
 }
 @Override
 public boolean onLongClick(View v) {
  // TODO 自動生成されたメソッド・スタブ
  button1.setText("onLongClick");
  return false;
 }
 @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO 自動生成されたメソッド・スタブ
  // ドラッグ
  switch (event.getAction() & MotionEvent.ACTION_MASK) {
  case MotionEvent.ACTION_DOWN:
   offsetX = (int) event.getX();
   offsetY = (int) event.getY();
   mState = STATE_DRAG;
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_POINTER_UP:
   mState = STATE_NONE;
   break;
  case MotionEvent.ACTION_MOVE:
   if (mState == STATE_DRAG) {
    int pointX, pointY;
    pointX = (int) event.getRawX() - offsetX;
    //ステータスバーの取得方法が不明のため直打ち(要変更)
    pointY = (int) event.getRawY() - (offsetY + 50);
    button1.layout(pointX, pointY, pointX + button1.getWidth(), pointY + button1.getHeight());
   }
   break;
  }
  return false;
 }
}

2010年12月24日金曜日

座標系について

前回スクリーン座標とローカル座標について話しましたがもう一つ座標系があったみたいです

赤がスクリーン座標で、緑がレイアウトの持つローカル座標、青がボタンの持つローカル座標

前回で言っていたスクリーン座標はレイアウトのローカル座標でした。申し訳ない・・・

それでボタン高さ分ずれる原因も判明しました
public void setLayoutParams (ViewGroup.LayoutParams params)
これでボタン座標を設定していますが、これの設定はレイアウトのローカル座標系に対しての設定です。なのでレイアウトのローカル座標からスクリーン座標に変換する必要があります。

前回ボタン高さ分ずらして位置があっているように見えてたのは偶然で本当は下の画像のオレンジ分の差分を考慮しなければいけません
オレンジ矢印の長さ求める方法は摸索中・・・
ステータスバー?呼び方分かればリファレンス見ればなんとか出てきそうかな

2010年12月22日水曜日

スクリーン座標とボタンのローカル座標

前回の投稿で軽く触れてましたがもうちょい詳しく書いておきます

赤い軸がスクリーン座標軸で青い軸がボタンの持つローカル座標軸
間違っていました(詳しくは次の投稿で)
それぞれの座標を取得する方法は

スクリーン座標
float android.view.MotionEvent.getRawX()

public final float getRawX ()

Since: API Level 1
Returns the original raw X coordinate of this event. For touch events on the screen, this is the original location of the event on the screen, before it had been adjusted for the containing window and views.


ローカル座標
 こっちは配列の先頭インデックスの座標を取得する
 タッチイベント中に座標を何個か保持してるみたいで下のメソッドでは最新の座標を取得する
 保持している座標の数などはgetHistorical***などが用意されている
float android.view.MotionEvent.getY()

public final float getX ()

Since: API Level 1
getX(int) for the first pointer index (may be an arbitrary pointer identifier).

詳しくはリファレンスのview.MotionEventのページ見るのが早い
http://developer.android.com/reference/android/view/MotionEvent.html


それで前回のプログラム(ドラッグ中の座標を取得してボタンに設定する)の補足です
主に座標変換について。
取得したスクリーン座標をそのままボタンに設定すると下の画像のようにボタンの左上になっちゃいます。これはボタンを設定する際は矩形の左上の座標を設定する仕様になっているためです。


そこで、ボタンをタップした時点でのローカル座標を取得してその分ずらす必要があります。



具体的には緑をタップしたときのローカル座標(getXなど)を保持しておいてドラッグ中のスクリーン座標(getRawXなど)に対して引いてあげると押した時まま一緒に移動してくれます。
詳しいことは前回の投稿の最後にあるソースを参照してください。


ここまで説明したのですがX方向に対しては上記の説明が正しいのですが
Y方向に関してはgetRawY()-getY()だけだとボタンのheight分ずれてしまいました。
なので前回のプログラムではgetRawY()-(geyY()+button.height)としています。
なんでだろう・・・

-----------------------------------------------------------------------------------------------------------------------------
//追記
分かった・・・
簡単にいうと座標系がもう一つあったということ
長くなりそうなんで新しい投稿で説明します

2010年12月21日火曜日

android.widget.Buttonの座標を設定する方法

ボタンの配置を自由にカスタマイズできるような仕様のアプリを作ろうとしていたがここではまった
やりたいことはドラッグ中の座標にButtonを再配置するということ
はまった点は
 ドラッグ中の座標の取得(主にローカルとスクリーン座標について)
 ボタンの座標の設定方法

はじめに言っておくと直接座標指定するって方法は推奨されていないみたいです
画面配置が機種依存になってしまうからかなって推測



まずボタンの座標を設定する方法ですが直接設定できるようなメソッドは調べた限りでは無かった
ボタンの座標の取得はgetLeft() getRight() getTop() getBottom()など取得できるが設定のためのsetLeft()などは無いみたい

Buttonを追加する土台となるレイアウトの種類によってはButtonを追加する際に呼ぶメソッドに座標を指定するパラメータが無いものがある
じゃあ座標指定できるレイアウトはなんぞやってことだがAbsoluteLayout で座標が指定できるようになる

 //レイアウト作成
  AbsoluteLayout absoluteLayout = new AbsoluteLayout(this);
  setContentView(absoluteLayout);
  //ボタン作成
  Button button1 = new Button(this);
 //レイアウトにボタンを追加 ボタンのパラメータの設定
  absoluteLayout.addView(button1, new AbsoluteLayout.LayoutParams(150,50, 0, 0));

こんな感じで指定した座標にボタンを追加することができる
指定しているコードはAbsoluteLayout.LayoutParams(width,height, x, y)で行っている
xyはButtonの矩形の左上の座標になる

ボタンのパラメータを動的に指定したい場合は
button1.setLayoutParams(new AbsoluteLayout.LayoutParams(width,height, x, y));
とすると指定したパラメータにボタンが更新される




次にドラッグ中の座標取得ですが
ドラッグの実装についてはどっかのサイトを見たんだけどどこか忘れた・・・
それで、はまったのはどの座標系の座標を取ってきているかを勘違いしていたってことで

android.view.MotionEvent.getX()

ボタンのローカル座標
ボタンの持っている座標系の座標を取得するもんだと思う
詳しくリファレンス読んでないので間違ってるかもしれない

android.view.MotionEvent.getRawX()
スクリーン座標
こちらはスクリーンの座標系の座標を取得するものだと思う


きっちり調べたわけではないので間違ってること言っていたらご指摘お願いします。





上で述べた二つを組み合わせて作ったのがボタンをドラッグ中の座標に設定するサンプルプログラム
import android.app.Activity;
import android.os.Bundle;
import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.Button;
import android.widget.TextView;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class AndroidFormTest extends Activity implements OnTouchListener {
 private Button button1;
 private TextView textView1, textView2,textView3;
 private int mState = 0;
 private int offsetX = 0;// ボタンクリックしたスクリーンのX座標とボタンのX座標の差分
 private int offsetY = 0;// ボタンクリックしたスクリーンのY座標とボタンのY座標の差分
 private final int STATE_NONE = 0;
 private final int STATE_DRAG = 1;
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  AbsoluteLayout absoluteLayout = new AbsoluteLayout(this);
  setContentView(absoluteLayout);
  //ボタン作成
  button1 = new Button(this);
  // イベントリスナの登録
  button1.setOnTouchListener(this);

  absoluteLayout.addView(button1, new AbsoluteLayout.LayoutParams(150,50, 0, 0));
  button1.setText(button1.getLeft() + "," + button1.getTop());
  textView1 = new TextView(this);
  absoluteLayout.addView(textView1, new AbsoluteLayout.LayoutParams(300,50, 20, 100));
  textView2 = new TextView(this);
  absoluteLayout.addView(textView2, new AbsoluteLayout.LayoutParams(300,50, 20, 150));
  textView3 = new TextView(this);
  absoluteLayout.addView(textView3, new AbsoluteLayout.LayoutParams(300,50, 20, 200));
 }
  @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO 自動生成されたメソッド・スタブ
  // ドラッグ
  switch (event.getAction() & MotionEvent.ACTION_MASK) {
  case MotionEvent.ACTION_DOWN:
   offsetX = (int) event.getX();
   offsetY = (int) event.getY();
   textView1.setText("クリックした時点のローカル:" + offsetX + "," + offsetY);
   mState = STATE_DRAG;
   break;
  case MotionEvent.ACTION_UP:
  case MotionEvent.ACTION_POINTER_UP:
   mState = STATE_NONE;
   break;
  case MotionEvent.ACTION_MOVE:
   if (mState == STATE_DRAG) {
    int pointX, pointY;
    pointX = (int) event.getRawX() - offsetX;
    pointY = (int) event.getRawY() - (offsetY + button1.getHeight());
    button1.setLayoutParams(new AbsoluteLayout.LayoutParams(150,50, pointX, pointY));
    textView2.setText("ボタン座標(左上):" + button1.getLeft() + "," + button1.getTop());
    textView3.setText("スクリーン座標:" + (int) event.getRawX() + "," + (int) event.getRawY());
   }
   break;
  }
  return false;
 }
}
------------------------------------------------------------------------------------------------------------
追記
58行目のpointY = (int) event.getRawY() - (offsetY + button1.getHeight());
をpointY = (int) event.getRawY() - (offsetY + ステータスバーの高さ);と変更してください。
今回はステータスバーの高さとボタンの高さがたまたま一緒だったのでうまくいっています。
ステータスバーの高さを取得できる方法が分かり次第また追記します。