このエントリーをはてなブックマークに追加

2010年4月25日日曜日

Android Intent to Take a Picture

[In English]
When we develop an application, sometimes we use camera function for it.
Of course we can implement our own camera function to our application using camera API, but most of Android Phone provide Camera application.
so today I'll show how to start up camera application and retrieve picture data from it using Intent.


final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);


We need to call Activity using startActivityForResult (not startActivity) to retrieve picture data.


protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) {
// get the picture
final Bitmap bitmap = (Bitmap) data.getExtras().get("data");
// do something for bitmap data
final String sUri = MediaStore.Images.Media.insertImage(
getContentResolver(), bitmap, timestamp, timestamp);



}
}


After taking a picture using Camera application, onActivityResult will be called. And then we can get picture data as Bitmap from extras.
But I feel the quality of bitmap data is not good in this case, because data size in intent extras is limited.



[In Japanese]
アプリケーションを作るときに、場合によってはカメラ機能を使うときもあると思います。
その際に、もちろんカメラAPIを使って独自にカメラ機能を実装することもできますが、ほとんどのAndroid携帯はカメラアプリを提供しています。
そこで、今日はIntentを使ってカメラアプリを起動させ、撮影した写真データを取得する方法を紹介します。


final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQUEST_CAMERA);


この場合、写真データを取得するために、startActivityではなく、startActivityForResultを使う必要があります。


protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CAMERA && resultCode == RESULT_OK) {
// get the picture
final Bitmap bitmap = (Bitmap) data.getExtras().get("data");
// do something for bitmap data
final String sUri = MediaStore.Images.Media.insertImage(
getContentResolver(), bitmap, timestamp, timestamp);



}
}


カメラアプリで写真を撮った後、onActivityResultが呼び出されます。そこで、写真データをBitmapとしてextrasから取得できます。
ただ、このBitmapのクオリティはあまりよくないように感じました、おそらくはIntentで渡せるデータサイズに制限があるためだと思います。

2010年4月19日月曜日

how to make kind of Twitter edit box

[In English]
Today, I'm going to make a component something like twitter edit box.
You know, edit box in http://twitter.com indicates the number of words that you can enter in real time.
EditText in Android SDK is not supported this function directory, so we need to implement similar function for ourselves.
We tend to think we can make it by applying a OnKeyListener to EditText.
But we can't in that way.

Basically OnKeyListener will inform you of hardware-keyboard events. But even in software-keyboard, OnKeyListener lets you know typical key events such as 'enter' or 'del'. But you cannot acquire whole events in software-keyborad.

In order to solve this problem, we create a new class extending EditText and then override onTextChanged method.
The method of 'onTextChanged' is called every time edit text is changed. Whichever software-keyboard or hardware-keyboard, you don't have to worry.

That way is very convenient solution this time. I wonder why onTextChanged method is provided as a listener. I think it's more useful for many occasions.

By the way, sample code is like this.


public class WordCountEditText extends EditText {

private TextView wordCountView;

private final static int MAX_LENGTH = 140;

public WordCountEditText(final Context context) {
super(context);
}

public WordCountEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
}

public WordCountEditText(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}

@Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
if (wordCountView != null) {
final int textColor;
int leftLength = MAX_LENGTH - text.length();
if (leftLength < 0) {
textColor = Color.RED;
} else {
textColor = Color.GRAY;
}
wordCountView.setTextColor(textColor);
wordCountView.setText(String.valueOf(leftLength));
}
}

public void setWordCountView(final TextView wordCountView) {
this.wordCountView = wordCountView;
setText(getText());
}
}


And sample code in using class above.


WordCountEditText wordCountEditText = (WordCountEditText)findViewById(R.id.edit_text);
TextView wordCountView = (TextView)findViewById(R.id.word_count_view);
wordCountEditText.setWordCountView(wordCountView);






[In Japanese]
今日は、Twitter風のエディットテキストを作成する方法をご紹介します。
ご存知の通り、http://twitter.com で提供されているエディットボックスは、入力可能な残りの文字数がリアルタイムで表示されます。
残念ながら、Android SDKで提供されているEditTextには、この機能はありません。なので自分達で似たような機能を実装する必要があります。
Android SDKに慣れている人の中には、EditTextにOnKeyListenerを登録する事で実現できると考える人も多いと思います。しかしこのOnKeyListenerは、主にハードウェアキーボードのイベントを通知する為のものです。
ソフトウェアキーボードでも、「確定」キーや「DEL」キーのような代表的なキーのイベントはOnKeyListenerでイベントの検知が可能ですが、全てのイベントを検知する事はできません。

この問題を解決する為には、EditTextを継承した新しいクラスを作成し、onTextChangedメソッドをオーバーライドします。
onTextChangedメソッドは、EditTextの内容が書き換わる度に必ず呼び出されます。ハードウェアキーボードによる変更かソフトウェアキーボーかを気にする必要がありません。

今回の問題を解決するには正にうってつけの方法です。予断ですが、なぜonTextChangedメソッド相当のListenerが提供されていないのかが不思議です。Listenerが提供されていれば、新しいクラスを作成する必要もありませんし、色々な場面で便利だと思うのですが。

とりあえず、サンプルソースは以下のようになります。


public class WordCountEditText extends EditText {

private TextView wordCountView;

private final static int MAX_LENGTH = 140;

public WordCountEditText(final Context context) {
super(context);
}

public WordCountEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
}

public WordCountEditText(final Context context, final AttributeSet attrs, final int defStyle) {
super(context, attrs, defStyle);
}

@Override
protected void onTextChanged(final CharSequence text, final int start, final int before, final int after) {
if (wordCountView != null) {
final int textColor;
int leftLength = MAX_LENGTH - text.length();
if (leftLength < 0) {
textColor = Color.RED;
} else {
textColor = Color.GRAY;
}
wordCountView.setTextColor(textColor);
wordCountView.setText(String.valueOf(leftLength));
}
}

public void setWordCountView(final TextView wordCountView) {
this.wordCountView = wordCountView;
setText(getText());
}
}


で、上記のクラスを使う側のコードが以下です。


WordCountEditText wordCountEditText = (WordCountEditText)findViewById(R.id.edit_text);
TextView wordCountView = (TextView)findViewById(R.id.word_count_view);
wordCountEditText.setWordCountView(wordCountView);

2010年4月8日木曜日

Android Intent to show Location Settings View

[In English]
LocationManager is used in Android to get device location and show the address.
But if location setting is disabled on the device settings, Provider will be NULL.


final LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
final LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
final String provider = mLocationManager.getBestProvider(criteria, true);


In the case of the above sample, it is okay only to notify the user with Dialog, but I think it is better to move to Location Settings View because our applications can call the other applications using Intent on Android.


final Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);


Like this if you use Intent, you will not need to implement all function you want to your applications.
I'll continue to write blogs about Intent of Camera, Gallery and so on.



[In Japanese]
Androidアプリで位置情報を取得して、住所などを表示させる場合には、LocationManagerを使用します。
ただ、端末の設定で位置情報の送信を許可していないとProviderとして、nullが返されます。


final LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
final Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
final LocationManager locationManager = (LocationManager)getSystemService(LOCATION_SERVICE);
final String provider = mLocationManager.getBestProvider(criteria, true);


nullが返された場合に、Dialogなどでユーザに通知するだけでもよいのですが、せっかくAndroidではIntentをつかって、他のアプリを呼び出せるので位置情報の設定画面へ遷移する方がよいと思います。


final Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(i);


このようにIntentを利用することで、他のアプリを呼び出せ、自分のアプリで全て実装する必要がなくなります。
今後もカメラやギャラリーなどの連携についてブログで紹介したいと思います。