Software/Android/アプリケーション開発テキスト/Chapter03
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
]
開始行:
[[Software/Android/アプリケーション開発テキスト]]
*Chapter 3 : インテントによる外部アプリケーションとの連携...
この章では画像リサイズツールの開発を通して、インテント...
このアプリケーションはインテントによりギャラリーやカメ...
新規Androidアプリケーションプロジェクトを以下の設定で作...
-Project Nameに「IResizer」と入力します
-Application Nameに「IResizer」と入力します
-Package Nameに「com.beatcraft.iresizer」と入力します
-Create Activityにチェックを入れ、「IResizerActivity」と...
~
~
**3-1. アプリケーションのレイアウト作成 [#s1bc295b]
今回作成するアプリケーションでは、縦画面時と横画面時で...
CENTER:&ref(./03_01.png,);
CENTER:図3-1~
~
CENTER:&ref(./03_02.png,);
CENTER:図3-2~
~
~
黒い余白部分は他アプリケーションから受け取った画像をプ...
レイアウトを作成する前に利用する文字列リソースを定義し...
<string name="select_image">画像を選択</string>
<string name="take_photo">写真を撮影</string>
<string name="label_w">横</string>
<string name="label_h">縦</string>
<string name="keep_ratio">比率を維持</string>
<string name="save">保存</string>
~
まずは操作部のレイアウトを作成します。IResizerをクリッ...
続く"New Android Layout XML File"でFileに「controller.x...
左部のPaletteからForm Widgetsをクリックして展開し、「Bu...
-Idに「@+id/SelectImage」と入力します。
-Textに「@string/select_image」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
同様にボタンをもう一つ追加して、以下のように設定を変更...
-Idに「@+id/TakePhoto」と入力します。
-Textに「@string/take_photo」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
続いて横サイズの入力項目を配置していきます。「LinearLay...
-Idに「@+id/WLayout」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WLabel」と入力します。
-Textに「@string/label_w」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
EditTextを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WSize」と入力します。
-Input typeに「number」を指定します。
-Layout heightに「wrap_content」を指定します。
-Layout weightに「1」と入力します。
-Layout widthに「wrap_content」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WSuffix」と入力します。
-Textに「px」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
縦サイズの入力項目も横サイズ同様に配置していきます。「L...
-Idに「@+id/HLayout」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HLabel」と入力します。
-Textに「@string/label_h」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
EditTextを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HSize」と入力します。
-Input typeに「number」を指定します。
-Layout heightに「wrap_content」を指定します。
-Layout weightに「1」と入力します。
-Layout widthに「wrap_content」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HSuffix」と入力します。
-Textに「px」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
続いてPaletteからForm Widgetsをクリックして展開し、「Ch...
-Checkedに「true」を指定します。
-Idに「@+id/KeepRatio」と入力します。
-Textに「@string/keep_ratio」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
最後にもう一つボタンを追加します。
-Idに「@+id/Save」と入力します。
-Textに「@string/save」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
以上で操作部のレイアウトは完成です。完成後のアウトライ...
|LEFT:|CENTER:|c
| LinearLayout&br; SelectImage&br; TakePhoto&br; ...
~
縦画面用のレイアウトを作成していきましょう。プロジェク...
次に左部のPaletteからImages & Mediaをクリックして展開し...
-Adjust view boundsに「true」を指定します。
-Idに「@+id/Preview」と入力します。
-Scale typeに「fitCenter」を指定します。
-Layout heightに「0dip」と入力します。
-Layout marginに「5dip」と入力します。
-Layout weightに「1」と入力します。
-Layout widthに「fill_parent」を指定します。
ここで先ほど作成した操作部レイアウトを取り込みます。レ...
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="@layout/controller" />
これで先ほど作成した操作部のレイアウトが取り込まれ、図3...
※Graphical Layoutタブで確認するとcontrollerリソースが無い...
~
同様にして横画面用のレイアウトも作成します。まずはIResi...
layoutフォルダにあるmain.xmlをドラッグ&ドロップでlayou...
まずは最上位にあるLinearLayoutの設定を以下のように変更...
-Orientationを「horizontal」に変更します。
続いてプレビュー用の画像ビュー(Preview)の設定を以下の...
-Layout heightを「fill_parent」に変更します。
最後に取り込んだcontrollerレイアウトの設定を以下のよう...
-Layout heightを「fill_parent」に変更します。
-Layout widthを「wrap_content」に変更します。
以上で横画面用レイアウトも完成です。Graphcal Layoutタブ...
**3-2. ユーザーインターフェースの実装 [#w40a8ae8]
前項で作成したレイアウトをアクティビティに反映し、ボタ...
IResizerActivity.javaを開き、IResizerActivityに以下のメ...
private ImageView mPreview;
private EditText mWSize;
private EditText mHSize;
private Bitmap mBitmap = null;
private int mOrgW = 0;
private int mOrgH = 0;
ImageViewとEditText、Bitmapクラスを利用可能にするために...
CENTER:&ref(./03_04.png,);
CENTER:図3-4~
~
mBitmap、mOrgWとmOrgHの三つのメンバ変数は他のアプリケー...
続いて、このクラスで各ボタンのクリック処理を行うためand...
import android.view.View;
public class IResizerActivity extends Activity implement...
onCreateメソッドの後にonClickメソッドと二つのprivateメ...
-リスト3-1 :
@Override
publiic void onClick(View view) {
}
private void setupUI() {
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.SelectImage);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.TakePhoto);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Save);
button.setOnClickListener(this);
mPreview = (ImageView) findViewById(R.id.Preview);
mWSize = (EditText) findViewById(R.id.WSize);
mHSize = (EditText) findViewById(R.id.HSize);
setPreview();
mWSize.setOnFocusChangeListener(new View.OnFocusChan...
@Override
public void onFocusChange(View v, boolean flag) {
if (flag == false) {
CheckBox keepRatio = (CheckBox) findView...
if (keepRatio.isChecked() == true) {
String base = mWSize.getText().toStr...
if ((base.equals("") == false)
&& (mOrgW != 0) && (mOrgH !=...
double h = 0;
double w = Integer.parseInt(base);
double ratio = (double) mOrgH / ...
h = new BigDecimal(w * ratio).se...
if (h < 1.0) {
h = 1.0;
}
mHSize.setText(String.valueOf((i...
}
}
}
}
});
mHSize.setOnFocusChangeListener(new View.OnFocusChan...
@Override
public void onFocusChange(View v, boolean flag) {
if (flag == false) {
CheckBox keepRatio = (CheckBox) findView...
if (keepRatio.isChecked() == true) {
String base = mHSize.getText().toStr...
if ((base.equals("") == false)
&& (mOrgW != 0) && (mOrgH !=...
double w = 0;
double h = Integer.parseInt(base);
double ratio = (double) mOrgW / ...
w = new BigDecimal(w * ratio).se...
if (w < 1.0) {
w = 1.0;
}
mWSize.setText(String.valueOf((i...
}
}
}
}
});
}
private void setPreview() {
if (mBitmap != null) {
mOrgW = mBitmap .getWidth();
mOrgH = mBitmap .getHeight();
mWSize.setText(String.valueOf(mOrgW));
mHSize.setText(String.valueOf(mOrgH));
mPreview.setImageBitmap(mBitmap);
}
}
~
setupUIメソッドではまず、setContentViewでmainレイアウト...
続いて画像プレビュー用のImageView、横/縦サイズ入力用Edi...
その後横/縦サイズ入力用EditTextそれぞれにOnFocusChangeL...
onFocusChangeはそのウィジェットのフォーカス状態が変更さ...
四捨五入で使用したBigDecimalと「比率を維持」チェックボ...
import java.math.BigDecimal;
import android.widget.CheckBox;
以上の作成が完了したら、自動生成されたonCreateを以下の...
-リスト3-2 :
/** Called when the activity is first created. */
@Override
publiic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setupUI();
}
~
元々のコードではここで直接setContentViewを呼び出してい...
CENTER:&ref(./03_05.png,);
CENTER:図3-5~
~
ここまでで一度アプリケーションを実行してみましょう。And...
**3-3. インテントによる外部アプリケーション呼び出し [#h77...
ここからは「画像を選択」ボタンと「写真を撮影」ボタンの...
まずは外部アプリケーション呼び出しに使用する二つの定数...
public static final int REQUEST_SELECT_IMAGE = 1234;
public static final int REQUEST_TAKE_PHOTO = 1235;
private Uri mUriFromCamera;
続いて前項で追加したonClickメソッドを以下のように変更し...
-リスト3-3 :
@Override
publiic void onClick(View view){
int id = view.getId();
switch (id) {
case R.id.SelectImage:
selectImage();
break;
case R.id.TakePhoto:
takePhoto();
break;
}
}
~
引数に渡されたviewからgetIdメソッドでIDを取得し、「画像...
これらのメソッドで使用する文字列リソースを追加しておき...
<string name="app_notfound">対応アプリケーションが...
リスト3-4がselectImageメソッドになります。Intent、Alert...
-リスト3-4 :
private void selectImage() {
try {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_SELECT_IM...
}
catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app_notfou...
builder.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dial...
}
}
);
builder.show();
}
}
~
tryブロックで囲まれた部分では、まずIntent.ACTION_PICKを...
今回のアプリケーションでは画像データを必要とするため、...
指定したインテントに対応可能なアクティビティをAndroidが...
続いてtakePhotoメソッドも実装していきます(リスト3-5)...
-リスト3-5 :
private void takePhoto() {
try {
Intent intent = new Intent(MediaStore.ACTION_IMA...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.MIME_TYPE, "i...
mUriFromCamera = getContentResolver().insert(
MediaStore.Images.Media. EXTERNAL_CONTENT_UR...
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriFro...
startActivityForResult(intent, REQUEST_TAKE_PHOT...
}
catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app_notfou...
builder.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dial...
}
}
);
builder.show();
}
}
~
カメラを呼び出すインテントにはMediaStore.ACTION_IMAGE_C...
これを先程追加したメンバ変数mUriFromCameraに保持してお...
再びアプリケーションを実行して「画像を選択」「写真を撮...
CENTER:&ref(./03_06.png,);
CENTER:図3-6~
~
**3-4. 外部アプリケーションからのデータ取得 [#a8315a05]
前項までで外部アプリケーションを呼び出すことが出来まし...
startActivityForResultで呼び出したアプリケーションから...
-リスト3-6 :
protected void onActivityResult(int reqCode, int result,...
super.onActivityResult(reqCode, result, data);
Uri uri = null;
if (result == RESULT_OK) {
if (reqCode == REQUEST_SELECT_IMAGE) {
uri = data.getData();
}
else if (reqCode == REQUEST_TAKE_PHOTO) {
uri = mUriFromCamera;
}
mBitmap = getImage(uri);
setPreview();
}
else if (reqCode == REQUEST_TAKE_PHOTO) {
getContentResolver().delete(mUriFromCamera, null...
}
}
~
superクラスのonActivityResultを呼び出した後、resultをチ...
reqCodeにはstartActivityResultを呼び出した際のリクエス...
一方"REQUEST_TAKE_PHOTO"の場合は「写真を撮影」での呼び...
取得したUriを後ほど実装するgetImageメソッドに引き渡して...
リスト3-7がgetImageメソッドになります。InputStream、Bit...
-リスト3-7 :
private Bitmap getImage(Uri uri) {
try {
InputStream is = getContentResolver().openInputS...
return BitmapFactory.decodeStream(is);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
~
ContentResolverのopenInputStreamメソッドにUriを渡すと、...
以上でデータ受け取りの実装は完了ですが、Androidのバージ...
IResizerのマニフェストファイル(AndroidManifest.xml)を...
-リスト3-8 :
<activity
android:configChanges="orientation"
android:label="@string/app_name"
android:name=".IResizerActivity" >
~
続いてIResizerActivity.javaにonConfigurationChangedメソ...
-リスト3-9 :
@Override
public void onConfigurationChanged(Configuration newConf...
super.onConfigurationChanged(newConfig);
setupUI();
}
~
superクラスのonConfigurationChangedを呼び出したあと、se...
~
**3-5. リサイズ画像保存処理の実装 [#af5fc665]
ここからは受け取った画像をリサイズし、保存するまでの処...
-フォーマットはJPEG固定とする。
-ファイル名は現在時刻を用いて「YYYYMMDD_HHMMSS.jpg」とい...
-保存先はカメラフォルダに固定とし、ギャラリーに表示される...
-保存前に確認ダイアログを表示する。
まずは保存処理で使用する文字列リソースを追加しておきま...
<string name="cancel">取消</string>
<string name="save_title">画像保存</string>
<string name="filename_label">ファイル名:</string>
<string name="isize_label">画像サイズ:</string>
<string name="save_desc">で保存します。</string>
<string name="save_success">保存しました</string>
<string name="save_failed">保存に失敗しました</string>
続いて確認ダイアログ用のレイアウトを作成していきます。I...
-リスト3-10 :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android....
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/FileNameLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/FileLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filename_label" />
<TextView
android:id="@+id/FileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/ImageSizeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/SizeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/isize_label" />
<TextView
android:id="@+id/ImageSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:gravity="right"
android:text="@string/save_desc" />
<LinearLayout
android:id="@+id/ButtonLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center_horizontal" >
<Button
android:id="@+id/ExecSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
~
ダイアログのアウトラインとレイアウトイメージは以下のよ...
|LEFT:|CENTER:|c
| LinearLayout&br; FileNameLayout&br; FileLabel&...
~
保存時のファイル名とダイアログを保持するため、IResizerA...
private String mFileName = "";
private Dialog mDialog = null;
IResizerActivityの「保存」ボタンに応答するため、onClick...
case R.id.Save:
showConfirmDialog();
break;
リスト3-11がshowConfirmDialogメソッドになります。DateFo...
-リスト3-11 :
private void showConfirmDialog() {
if ((mBitmap != null)
&& (mWSize.getText().toString().trim().equal...
&& (mHSize.getText().toString().trim().equal...
long ctime = System.currentTimeMillis();
mFileName = DateFormat.format("yyyyMMdd_kkmmss",...
mDialog = new Dialog(this);
mDialog.setContentView(R.layout.dialog);
mDialog.setTitle(getString(R.string.save_title));
Button button;
button = (Button) mDialog.findViewById(R.id.Exec...
button.setOnClickListener(this);
button = (Button) mDialog.findViewById(R.id.Canc...
button.setOnClickListener(this);
TextView tv;
tv = (TextView) mDialog.findViewById(R.id.FileNa...
tv.setText(mFileName);
tv = (TextView) mDialog.findViewById(R.id.ImageS...
tv.setText(mWSize.getText().toString() + "x" + m...
mDialog.show();
}
}
~
リサイズ元画像とリサイズ解像度が空でないことを確認し、...
次にDialogオブジェクトを生成して先ほどのレイアウトを割...
ダイアログの両ボタンに応答するため、onClickのswitchに以...
case R.id.ExecSave:
case R.id.Cancel:
if (mDialog != null) {
if (id == R.id.ExecSave) {
execSave();
}
mDialog.dismiss();
mDialog = null;
}
break;
~
「保存」「取消」両ボタンとも、ダイアログがnullでなけれ...
リスト3-12がexecSaveメソッドになります。Toastのパッケー...
-リスト3-12 :
private void execSave() {
int w = Integer.parseInt(mWSize.getText().toString());
int h = Integer.parseInt(mHSize.getText().toString());
Bitmap bitmap = Bitmap.createScaledBitmap(mBitmap, w...
try {
MediaStore.Images.Media.insertImage(getContentRe...
Toast.makeText(this, getString(R.string.save_suc...
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, getString(R.string.save_fai...
}
}
~
横/縦サイズ用EditTextからサイズを取得したら、Bitmap.cre...
生成した画像をMediaStore.Images.Media.insertImageメソッ...
これでリサイズ画像を保存することが出来るようになりまし...
CENTER:&ref(./03_08.png,);
CENTER:図3-8~
~
保存に失敗する場合、保存先が外部ストレージになっている...
<uses-permission android:name="android.permission.WR...
~
**3-6. 共有機能による他アプリケーションからの呼び出し [#k...
前項まででインテントを利用して外部アプリケーションと連...
画像の共有先としてIResizerを選択可能にするには、アクテ...
<intent-filter >
<category android:name="android.intent.c...
<data android:mimeType="image/*" />
<action android:name="android.intent.act...
</intent-filter>
~
これで画像アプリケーションの共有メニューにIResizerが表...
if(Intent.ACTION_SEND.equals(getIntent().getActi...
Uri uri = getIntent().getParcelableExtra(In...
mBitmap = getImage(uri);
setPreview();
}
~
これで完成です。ギャラリーなどの共有機能を持った画像ア...
CENTER:&ref(./03_09.png,);
CENTER:図3-9~
~
**3-7. IResizer全ソースコード/XMLファイル [#mbd93e73]
-リスト3-13 IResizerActivity.java :
package com.beatcraft.iresizer;
import java.io.InputStream;
import java.math.BigDecimal;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.format.DateFormat;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class IResizerActivity extends Activity implement...
public static final int REQUEST_SELECT_IMAGE = 1234;
public static final int REQUEST_TAKE_PHOTO = 1235;
private ImageView mPreview;
private EditText mWSize;
private EditText mHSize;
private Bitmap mBitmap = null;
private int mOrgW = 0;
private int mOrgH = 0;
private Uri mUriFromCamera;
private String mFileName = "";
private Dialog mDialog = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setupUI();
if (Intent.ACTION_SEND.equals(getIntent().getA...
Uri uri = getIntent().getParcelableExtra(...
mBitmap = getImage(uri);
setPreview();
}
}
@Override
public void onConfigurationChanged(Configuration ne...
super.onConfigurationChanged(newConfig);
setupUI();
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.SelectImage:
selectImage();
break;
case R.id.TakePhoto:
takePhoto();
break;
case R.id.Save:
showConfirmDialog();
break;
case R.id.ExecSave:
case R.id.Cancel:
if (mDialog != null) {
if (id == R.id.ExecSave) {
execSave();
}
mDialog.dismiss();
mDialog = null;
}
break;
}
}
protected void onActivityResult(int reqCode, int re...
super.onActivityResult(reqCode, result, data);
Uri uri = null;
if (result == RESULT_OK) {
if (reqCode == REQUEST_SELECT_IMAGE) {
uri = data.getData();
} else if (reqCode == REQUEST_TAKE_PHOTO) {
uri = mUriFromCamera;
}
mBitmap = getImage(uri);
setPreview();
} else if (reqCode == REQUEST_TAKE_PHOTO) {
getContentResolver().delete(mUriFromCamer...
}
}
private void setupUI() {
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.SelectImag...
button.setOnClickListener(this);
button = (Button) findViewById(R.id.TakePhoto);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Save);
button.setOnClickListener(this);
mPreview = (ImageView) findViewById(R.id.Previ...
mWSize = (EditText) findViewById(R.id.WSize);
mHSize = (EditText) findViewById(R.id.HSize);
setPreview();
mWSize.setOnFocusChangeListener(new View.OnFoc...
@Override
public void onFocusChange(View v, boolean...
if (flag == false) {
CheckBox keepRatio = (CheckBox)...
if (keepRatio.isChecked() == tr...
String base = mWSize.getTe...
if ((base.equals("") == fa...
&& (mOrgH != 0)) {
double h = 0;
double w = Integer.pa...
double ratio = (doubl...
h = new BigDecimal(w ...
BigDecimal....
if (h < 1.0) {
h = 1.0;
}
mHSize.setText(String...
}
}
}
}
});
mHSize.setOnFocusChangeListener(new View.OnFoc...
@Override
public void onFocusChange(View v, boolean...
if (flag == false) {
CheckBox keepRatio = (CheckBox)...
if (keepRatio.isChecked() == tr...
String base = mHSize.getTe...
if ((base.equals("") == fa...
&& (mOrgH != 0)) {
double w = 0;
double h = Integer.pa...
double ratio = (doubl...
w = new BigDecimal(h ...
BigDecimal....
if (w < 1.0) {
w = 1.0;
}
mWSize.setText(String...
}
}
}
}
});
}
private void selectImage() {
try {
Intent intent = new Intent(Intent.ACTION_...
intent.setType("image/*");
startActivityForResult(intent, REQUEST_SE...
} catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app...
builder.setNeutralButton("OK",
new DialogInterface.OnClickList...
@Override
public void onClick(Dialog...
}
});
builder.show();
}
}
private void takePhoto() {
try {
Intent intent = new Intent(MediaStore.ACT...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.MIME_T...
mUriFromCamera = getContentResolver().ins...
MediaStore.Images.Media.EXTERNA...
intent.putExtra(MediaStore.EXTRA_OUTPUT, ...
startActivityForResult(intent, REQUEST_TA...
} catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app...
builder.setNeutralButton("OK",
new DialogInterface.OnClickList...
@Override
public void onClick(Dialog...
}
});
builder.show();
}
}
private void showConfirmDialog() {
if ((mBitmap != null)
&& (mWSize.getText().toString().trim...
&& (mHSize.getText().toString().trim...
long ctime = System.currentTimeMillis();
mFileName = DateFormat.format("yyyyMMdd_k...
+ ".jpg";
mDialog = new Dialog(this);
mDialog.setContentView(R.layout.dialog);
mDialog.setTitle(getString(R.string.save_...
Button button;
button = (Button) mDialog.findViewById(R....
button.setOnClickListener(this);
button = (Button) mDialog.findViewById(R....
button.setOnClickListener(this);
TextView tv;
tv = (TextView) mDialog.findViewById(R.id...
tv.setText(mFileName);
tv = (TextView) mDialog.findViewById(R.id...
tv.setText(mWSize.getText().toString() + ...
+ mHSize.getText().toString());
mDialog.show();
}
}
private void execSave() {
int w = Integer.parseInt(mWSize.getText().toStr...
int h = Integer.parseInt(mHSize.getText().toSt...
Bitmap bitmap = Bitmap.createScaledBitmap(mBit...
try {
MediaStore.Images.Media.insertImage(getCo...
mFileName, null);
Toast.makeText(this, getString(R.string.s...
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, getString(R.string.s...
Toast.LENGTH_SHORT).show();
}
}
private Bitmap getImage(Uri uri) {
try {
InputStream is = getContentResolver().ope...
return BitmapFactory.decodeStream(is);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void setPreview() {
if (mBitmap != null) {
mOrgW = mBitmap.getWidth();
mOrgH = mBitmap.getHeight();
mWSize.setText(String.valueOf(mOrgW));
mHSize.setText(String.valueOf(mOrgH));
mPreview.setImageBitmap(mBitmap);
}
}
}
~
-リスト3-14 controller.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/SelectImage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/select_image" />
<Button
android:id="@+id/TakePhoto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/take_photo" />
<LinearLayout
android:id="@+id/WLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/WLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_w" />
<EditText
android:id="@+id/WSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/WSuffix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="px" />
</LinearLayout>
<LinearLayout
android:id="@+id/HLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/HLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_h" />
<EditText
android:id="@+id/HSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number" >
</EditText>
<TextView
android:id="@+id/HSuffix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="px" />
</LinearLayout>
<CheckBox
android:id="@+id/KeepRatio"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:checked="true"
android:text="@string/keep_ratio" />
<Button
android:id="@+id/Save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/save" />
</LinearLayout>
~
-リスト3-15 layout/main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/Preview"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_margin="5dip"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="@layout/controller" />
</LinearLayout>
~
-リスト3-16 layout-land/main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/Preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="5dip"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<include
android:layout_width="wrap_content"
android:layout_height="fill_parent"
layout="@layout/controller" />
</LinearLayout>
~
-リスト3-17 dialog.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/FileNameLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/FileLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filename_label" />
<TextView
android:id="@+id/FileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/ImageSizeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/SizeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/isize_label" />
<TextView
android:id="@+id/ImageSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:gravity="right"
android:text="@string/save_desc" />
<LinearLayout
android:id="@+id/ButtonLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center_horizontal" >
<Button
android:id="@+id/ExecSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
~
-リスト3-18 AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/...
package="com.beatcraft.iresizer"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:configChanges="orientation"
android:label="@string/app_name"
android:name=".IResizerActivity" >
<intent-filter >
<action android:name="android.intent.act...
<category android:name="android.intent.c...
</intent-filter>
<intent-filter >
<category android:name="android.intent.c...
<data android:mimeType="image/*" />
<action android:name="android.intent.act...
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WR...
</manifest>
~
----
RIGHT:内藤
終了行:
[[Software/Android/アプリケーション開発テキスト]]
*Chapter 3 : インテントによる外部アプリケーションとの連携...
この章では画像リサイズツールの開発を通して、インテント...
このアプリケーションはインテントによりギャラリーやカメ...
新規Androidアプリケーションプロジェクトを以下の設定で作...
-Project Nameに「IResizer」と入力します
-Application Nameに「IResizer」と入力します
-Package Nameに「com.beatcraft.iresizer」と入力します
-Create Activityにチェックを入れ、「IResizerActivity」と...
~
~
**3-1. アプリケーションのレイアウト作成 [#s1bc295b]
今回作成するアプリケーションでは、縦画面時と横画面時で...
CENTER:&ref(./03_01.png,);
CENTER:図3-1~
~
CENTER:&ref(./03_02.png,);
CENTER:図3-2~
~
~
黒い余白部分は他アプリケーションから受け取った画像をプ...
レイアウトを作成する前に利用する文字列リソースを定義し...
<string name="select_image">画像を選択</string>
<string name="take_photo">写真を撮影</string>
<string name="label_w">横</string>
<string name="label_h">縦</string>
<string name="keep_ratio">比率を維持</string>
<string name="save">保存</string>
~
まずは操作部のレイアウトを作成します。IResizerをクリッ...
続く"New Android Layout XML File"でFileに「controller.x...
左部のPaletteからForm Widgetsをクリックして展開し、「Bu...
-Idに「@+id/SelectImage」と入力します。
-Textに「@string/select_image」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
同様にボタンをもう一つ追加して、以下のように設定を変更...
-Idに「@+id/TakePhoto」と入力します。
-Textに「@string/take_photo」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
続いて横サイズの入力項目を配置していきます。「LinearLay...
-Idに「@+id/WLayout」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WLabel」と入力します。
-Textに「@string/label_w」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
EditTextを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WSize」と入力します。
-Input typeに「number」を指定します。
-Layout heightに「wrap_content」を指定します。
-Layout weightに「1」と入力します。
-Layout widthに「wrap_content」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/WSuffix」と入力します。
-Textに「px」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
縦サイズの入力項目も横サイズ同様に配置していきます。「L...
-Idに「@+id/HLayout」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HLabel」と入力します。
-Textに「@string/label_h」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
EditTextを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HSize」と入力します。
-Input typeに「number」を指定します。
-Layout heightに「wrap_content」を指定します。
-Layout weightに「1」と入力します。
-Layout widthに「wrap_content」を指定します。
TextViewを上記レイアウトに追加し、以下のように設定を変...
-Idに「@+id/HSuffix」と入力します。
-Textに「px」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout widthに「wrap_content」を指定します。
続いてPaletteからForm Widgetsをクリックして展開し、「Ch...
-Checkedに「true」を指定します。
-Idに「@+id/KeepRatio」と入力します。
-Textに「@string/keep_ratio」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
最後にもう一つボタンを追加します。
-Idに「@+id/Save」と入力します。
-Textに「@string/save」と入力します。
-Layout heightに「wrap_content」を指定します。
-Layout margin leftとLayout margin rightに「10dip」と入力...
-Layout widthに「fill_parent」を指定します。
以上で操作部のレイアウトは完成です。完成後のアウトライ...
|LEFT:|CENTER:|c
| LinearLayout&br; SelectImage&br; TakePhoto&br; ...
~
縦画面用のレイアウトを作成していきましょう。プロジェク...
次に左部のPaletteからImages & Mediaをクリックして展開し...
-Adjust view boundsに「true」を指定します。
-Idに「@+id/Preview」と入力します。
-Scale typeに「fitCenter」を指定します。
-Layout heightに「0dip」と入力します。
-Layout marginに「5dip」と入力します。
-Layout weightに「1」と入力します。
-Layout widthに「fill_parent」を指定します。
ここで先ほど作成した操作部レイアウトを取り込みます。レ...
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="@layout/controller" />
これで先ほど作成した操作部のレイアウトが取り込まれ、図3...
※Graphical Layoutタブで確認するとcontrollerリソースが無い...
~
同様にして横画面用のレイアウトも作成します。まずはIResi...
layoutフォルダにあるmain.xmlをドラッグ&ドロップでlayou...
まずは最上位にあるLinearLayoutの設定を以下のように変更...
-Orientationを「horizontal」に変更します。
続いてプレビュー用の画像ビュー(Preview)の設定を以下の...
-Layout heightを「fill_parent」に変更します。
最後に取り込んだcontrollerレイアウトの設定を以下のよう...
-Layout heightを「fill_parent」に変更します。
-Layout widthを「wrap_content」に変更します。
以上で横画面用レイアウトも完成です。Graphcal Layoutタブ...
**3-2. ユーザーインターフェースの実装 [#w40a8ae8]
前項で作成したレイアウトをアクティビティに反映し、ボタ...
IResizerActivity.javaを開き、IResizerActivityに以下のメ...
private ImageView mPreview;
private EditText mWSize;
private EditText mHSize;
private Bitmap mBitmap = null;
private int mOrgW = 0;
private int mOrgH = 0;
ImageViewとEditText、Bitmapクラスを利用可能にするために...
CENTER:&ref(./03_04.png,);
CENTER:図3-4~
~
mBitmap、mOrgWとmOrgHの三つのメンバ変数は他のアプリケー...
続いて、このクラスで各ボタンのクリック処理を行うためand...
import android.view.View;
public class IResizerActivity extends Activity implement...
onCreateメソッドの後にonClickメソッドと二つのprivateメ...
-リスト3-1 :
@Override
publiic void onClick(View view) {
}
private void setupUI() {
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.SelectImage);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.TakePhoto);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Save);
button.setOnClickListener(this);
mPreview = (ImageView) findViewById(R.id.Preview);
mWSize = (EditText) findViewById(R.id.WSize);
mHSize = (EditText) findViewById(R.id.HSize);
setPreview();
mWSize.setOnFocusChangeListener(new View.OnFocusChan...
@Override
public void onFocusChange(View v, boolean flag) {
if (flag == false) {
CheckBox keepRatio = (CheckBox) findView...
if (keepRatio.isChecked() == true) {
String base = mWSize.getText().toStr...
if ((base.equals("") == false)
&& (mOrgW != 0) && (mOrgH !=...
double h = 0;
double w = Integer.parseInt(base);
double ratio = (double) mOrgH / ...
h = new BigDecimal(w * ratio).se...
if (h < 1.0) {
h = 1.0;
}
mHSize.setText(String.valueOf((i...
}
}
}
}
});
mHSize.setOnFocusChangeListener(new View.OnFocusChan...
@Override
public void onFocusChange(View v, boolean flag) {
if (flag == false) {
CheckBox keepRatio = (CheckBox) findView...
if (keepRatio.isChecked() == true) {
String base = mHSize.getText().toStr...
if ((base.equals("") == false)
&& (mOrgW != 0) && (mOrgH !=...
double w = 0;
double h = Integer.parseInt(base);
double ratio = (double) mOrgW / ...
w = new BigDecimal(w * ratio).se...
if (w < 1.0) {
w = 1.0;
}
mWSize.setText(String.valueOf((i...
}
}
}
}
});
}
private void setPreview() {
if (mBitmap != null) {
mOrgW = mBitmap .getWidth();
mOrgH = mBitmap .getHeight();
mWSize.setText(String.valueOf(mOrgW));
mHSize.setText(String.valueOf(mOrgH));
mPreview.setImageBitmap(mBitmap);
}
}
~
setupUIメソッドではまず、setContentViewでmainレイアウト...
続いて画像プレビュー用のImageView、横/縦サイズ入力用Edi...
その後横/縦サイズ入力用EditTextそれぞれにOnFocusChangeL...
onFocusChangeはそのウィジェットのフォーカス状態が変更さ...
四捨五入で使用したBigDecimalと「比率を維持」チェックボ...
import java.math.BigDecimal;
import android.widget.CheckBox;
以上の作成が完了したら、自動生成されたonCreateを以下の...
-リスト3-2 :
/** Called when the activity is first created. */
@Override
publiic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setupUI();
}
~
元々のコードではここで直接setContentViewを呼び出してい...
CENTER:&ref(./03_05.png,);
CENTER:図3-5~
~
ここまでで一度アプリケーションを実行してみましょう。And...
**3-3. インテントによる外部アプリケーション呼び出し [#h77...
ここからは「画像を選択」ボタンと「写真を撮影」ボタンの...
まずは外部アプリケーション呼び出しに使用する二つの定数...
public static final int REQUEST_SELECT_IMAGE = 1234;
public static final int REQUEST_TAKE_PHOTO = 1235;
private Uri mUriFromCamera;
続いて前項で追加したonClickメソッドを以下のように変更し...
-リスト3-3 :
@Override
publiic void onClick(View view){
int id = view.getId();
switch (id) {
case R.id.SelectImage:
selectImage();
break;
case R.id.TakePhoto:
takePhoto();
break;
}
}
~
引数に渡されたviewからgetIdメソッドでIDを取得し、「画像...
これらのメソッドで使用する文字列リソースを追加しておき...
<string name="app_notfound">対応アプリケーションが...
リスト3-4がselectImageメソッドになります。Intent、Alert...
-リスト3-4 :
private void selectImage() {
try {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_SELECT_IM...
}
catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app_notfou...
builder.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dial...
}
}
);
builder.show();
}
}
~
tryブロックで囲まれた部分では、まずIntent.ACTION_PICKを...
今回のアプリケーションでは画像データを必要とするため、...
指定したインテントに対応可能なアクティビティをAndroidが...
続いてtakePhotoメソッドも実装していきます(リスト3-5)...
-リスト3-5 :
private void takePhoto() {
try {
Intent intent = new Intent(MediaStore.ACTION_IMA...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.MIME_TYPE, "i...
mUriFromCamera = getContentResolver().insert(
MediaStore.Images.Media. EXTERNAL_CONTENT_UR...
intent.putExtra(MediaStore.EXTRA_OUTPUT, mUriFro...
startActivityForResult(intent, REQUEST_TAKE_PHOT...
}
catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app_notfou...
builder.setNeutralButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dial...
}
}
);
builder.show();
}
}
~
カメラを呼び出すインテントにはMediaStore.ACTION_IMAGE_C...
これを先程追加したメンバ変数mUriFromCameraに保持してお...
再びアプリケーションを実行して「画像を選択」「写真を撮...
CENTER:&ref(./03_06.png,);
CENTER:図3-6~
~
**3-4. 外部アプリケーションからのデータ取得 [#a8315a05]
前項までで外部アプリケーションを呼び出すことが出来まし...
startActivityForResultで呼び出したアプリケーションから...
-リスト3-6 :
protected void onActivityResult(int reqCode, int result,...
super.onActivityResult(reqCode, result, data);
Uri uri = null;
if (result == RESULT_OK) {
if (reqCode == REQUEST_SELECT_IMAGE) {
uri = data.getData();
}
else if (reqCode == REQUEST_TAKE_PHOTO) {
uri = mUriFromCamera;
}
mBitmap = getImage(uri);
setPreview();
}
else if (reqCode == REQUEST_TAKE_PHOTO) {
getContentResolver().delete(mUriFromCamera, null...
}
}
~
superクラスのonActivityResultを呼び出した後、resultをチ...
reqCodeにはstartActivityResultを呼び出した際のリクエス...
一方"REQUEST_TAKE_PHOTO"の場合は「写真を撮影」での呼び...
取得したUriを後ほど実装するgetImageメソッドに引き渡して...
リスト3-7がgetImageメソッドになります。InputStream、Bit...
-リスト3-7 :
private Bitmap getImage(Uri uri) {
try {
InputStream is = getContentResolver().openInputS...
return BitmapFactory.decodeStream(is);
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
~
ContentResolverのopenInputStreamメソッドにUriを渡すと、...
以上でデータ受け取りの実装は完了ですが、Androidのバージ...
IResizerのマニフェストファイル(AndroidManifest.xml)を...
-リスト3-8 :
<activity
android:configChanges="orientation"
android:label="@string/app_name"
android:name=".IResizerActivity" >
~
続いてIResizerActivity.javaにonConfigurationChangedメソ...
-リスト3-9 :
@Override
public void onConfigurationChanged(Configuration newConf...
super.onConfigurationChanged(newConfig);
setupUI();
}
~
superクラスのonConfigurationChangedを呼び出したあと、se...
~
**3-5. リサイズ画像保存処理の実装 [#af5fc665]
ここからは受け取った画像をリサイズし、保存するまでの処...
-フォーマットはJPEG固定とする。
-ファイル名は現在時刻を用いて「YYYYMMDD_HHMMSS.jpg」とい...
-保存先はカメラフォルダに固定とし、ギャラリーに表示される...
-保存前に確認ダイアログを表示する。
まずは保存処理で使用する文字列リソースを追加しておきま...
<string name="cancel">取消</string>
<string name="save_title">画像保存</string>
<string name="filename_label">ファイル名:</string>
<string name="isize_label">画像サイズ:</string>
<string name="save_desc">で保存します。</string>
<string name="save_success">保存しました</string>
<string name="save_failed">保存に失敗しました</string>
続いて確認ダイアログ用のレイアウトを作成していきます。I...
-リスト3-10 :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android....
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/FileNameLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/FileLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filename_label" />
<TextView
android:id="@+id/FileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/ImageSizeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/SizeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/isize_label" />
<TextView
android:id="@+id/ImageSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:gravity="right"
android:text="@string/save_desc" />
<LinearLayout
android:id="@+id/ButtonLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center_horizontal" >
<Button
android:id="@+id/ExecSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
~
ダイアログのアウトラインとレイアウトイメージは以下のよ...
|LEFT:|CENTER:|c
| LinearLayout&br; FileNameLayout&br; FileLabel&...
~
保存時のファイル名とダイアログを保持するため、IResizerA...
private String mFileName = "";
private Dialog mDialog = null;
IResizerActivityの「保存」ボタンに応答するため、onClick...
case R.id.Save:
showConfirmDialog();
break;
リスト3-11がshowConfirmDialogメソッドになります。DateFo...
-リスト3-11 :
private void showConfirmDialog() {
if ((mBitmap != null)
&& (mWSize.getText().toString().trim().equal...
&& (mHSize.getText().toString().trim().equal...
long ctime = System.currentTimeMillis();
mFileName = DateFormat.format("yyyyMMdd_kkmmss",...
mDialog = new Dialog(this);
mDialog.setContentView(R.layout.dialog);
mDialog.setTitle(getString(R.string.save_title));
Button button;
button = (Button) mDialog.findViewById(R.id.Exec...
button.setOnClickListener(this);
button = (Button) mDialog.findViewById(R.id.Canc...
button.setOnClickListener(this);
TextView tv;
tv = (TextView) mDialog.findViewById(R.id.FileNa...
tv.setText(mFileName);
tv = (TextView) mDialog.findViewById(R.id.ImageS...
tv.setText(mWSize.getText().toString() + "x" + m...
mDialog.show();
}
}
~
リサイズ元画像とリサイズ解像度が空でないことを確認し、...
次にDialogオブジェクトを生成して先ほどのレイアウトを割...
ダイアログの両ボタンに応答するため、onClickのswitchに以...
case R.id.ExecSave:
case R.id.Cancel:
if (mDialog != null) {
if (id == R.id.ExecSave) {
execSave();
}
mDialog.dismiss();
mDialog = null;
}
break;
~
「保存」「取消」両ボタンとも、ダイアログがnullでなけれ...
リスト3-12がexecSaveメソッドになります。Toastのパッケー...
-リスト3-12 :
private void execSave() {
int w = Integer.parseInt(mWSize.getText().toString());
int h = Integer.parseInt(mHSize.getText().toString());
Bitmap bitmap = Bitmap.createScaledBitmap(mBitmap, w...
try {
MediaStore.Images.Media.insertImage(getContentRe...
Toast.makeText(this, getString(R.string.save_suc...
}
catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, getString(R.string.save_fai...
}
}
~
横/縦サイズ用EditTextからサイズを取得したら、Bitmap.cre...
生成した画像をMediaStore.Images.Media.insertImageメソッ...
これでリサイズ画像を保存することが出来るようになりまし...
CENTER:&ref(./03_08.png,);
CENTER:図3-8~
~
保存に失敗する場合、保存先が外部ストレージになっている...
<uses-permission android:name="android.permission.WR...
~
**3-6. 共有機能による他アプリケーションからの呼び出し [#k...
前項まででインテントを利用して外部アプリケーションと連...
画像の共有先としてIResizerを選択可能にするには、アクテ...
<intent-filter >
<category android:name="android.intent.c...
<data android:mimeType="image/*" />
<action android:name="android.intent.act...
</intent-filter>
~
これで画像アプリケーションの共有メニューにIResizerが表...
if(Intent.ACTION_SEND.equals(getIntent().getActi...
Uri uri = getIntent().getParcelableExtra(In...
mBitmap = getImage(uri);
setPreview();
}
~
これで完成です。ギャラリーなどの共有機能を持った画像ア...
CENTER:&ref(./03_09.png,);
CENTER:図3-9~
~
**3-7. IResizer全ソースコード/XMLファイル [#mbd93e73]
-リスト3-13 IResizerActivity.java :
package com.beatcraft.iresizer;
import java.io.InputStream;
import java.math.BigDecimal;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.format.DateFormat;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class IResizerActivity extends Activity implement...
public static final int REQUEST_SELECT_IMAGE = 1234;
public static final int REQUEST_TAKE_PHOTO = 1235;
private ImageView mPreview;
private EditText mWSize;
private EditText mHSize;
private Bitmap mBitmap = null;
private int mOrgW = 0;
private int mOrgH = 0;
private Uri mUriFromCamera;
private String mFileName = "";
private Dialog mDialog = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setupUI();
if (Intent.ACTION_SEND.equals(getIntent().getA...
Uri uri = getIntent().getParcelableExtra(...
mBitmap = getImage(uri);
setPreview();
}
}
@Override
public void onConfigurationChanged(Configuration ne...
super.onConfigurationChanged(newConfig);
setupUI();
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.SelectImage:
selectImage();
break;
case R.id.TakePhoto:
takePhoto();
break;
case R.id.Save:
showConfirmDialog();
break;
case R.id.ExecSave:
case R.id.Cancel:
if (mDialog != null) {
if (id == R.id.ExecSave) {
execSave();
}
mDialog.dismiss();
mDialog = null;
}
break;
}
}
protected void onActivityResult(int reqCode, int re...
super.onActivityResult(reqCode, result, data);
Uri uri = null;
if (result == RESULT_OK) {
if (reqCode == REQUEST_SELECT_IMAGE) {
uri = data.getData();
} else if (reqCode == REQUEST_TAKE_PHOTO) {
uri = mUriFromCamera;
}
mBitmap = getImage(uri);
setPreview();
} else if (reqCode == REQUEST_TAKE_PHOTO) {
getContentResolver().delete(mUriFromCamer...
}
}
private void setupUI() {
setContentView(R.layout.main);
Button button;
button = (Button) findViewById(R.id.SelectImag...
button.setOnClickListener(this);
button = (Button) findViewById(R.id.TakePhoto);
button.setOnClickListener(this);
button = (Button) findViewById(R.id.Save);
button.setOnClickListener(this);
mPreview = (ImageView) findViewById(R.id.Previ...
mWSize = (EditText) findViewById(R.id.WSize);
mHSize = (EditText) findViewById(R.id.HSize);
setPreview();
mWSize.setOnFocusChangeListener(new View.OnFoc...
@Override
public void onFocusChange(View v, boolean...
if (flag == false) {
CheckBox keepRatio = (CheckBox)...
if (keepRatio.isChecked() == tr...
String base = mWSize.getTe...
if ((base.equals("") == fa...
&& (mOrgH != 0)) {
double h = 0;
double w = Integer.pa...
double ratio = (doubl...
h = new BigDecimal(w ...
BigDecimal....
if (h < 1.0) {
h = 1.0;
}
mHSize.setText(String...
}
}
}
}
});
mHSize.setOnFocusChangeListener(new View.OnFoc...
@Override
public void onFocusChange(View v, boolean...
if (flag == false) {
CheckBox keepRatio = (CheckBox)...
if (keepRatio.isChecked() == tr...
String base = mHSize.getTe...
if ((base.equals("") == fa...
&& (mOrgH != 0)) {
double w = 0;
double h = Integer.pa...
double ratio = (doubl...
w = new BigDecimal(h ...
BigDecimal....
if (w < 1.0) {
w = 1.0;
}
mWSize.setText(String...
}
}
}
}
});
}
private void selectImage() {
try {
Intent intent = new Intent(Intent.ACTION_...
intent.setType("image/*");
startActivityForResult(intent, REQUEST_SE...
} catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app...
builder.setNeutralButton("OK",
new DialogInterface.OnClickList...
@Override
public void onClick(Dialog...
}
});
builder.show();
}
}
private void takePhoto() {
try {
Intent intent = new Intent(MediaStore.ACT...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.MIME_T...
mUriFromCamera = getContentResolver().ins...
MediaStore.Images.Media.EXTERNA...
intent.putExtra(MediaStore.EXTRA_OUTPUT, ...
startActivityForResult(intent, REQUEST_TA...
} catch (Exception e) {
AlertDialog.Builder builder = null;
builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.app...
builder.setNeutralButton("OK",
new DialogInterface.OnClickList...
@Override
public void onClick(Dialog...
}
});
builder.show();
}
}
private void showConfirmDialog() {
if ((mBitmap != null)
&& (mWSize.getText().toString().trim...
&& (mHSize.getText().toString().trim...
long ctime = System.currentTimeMillis();
mFileName = DateFormat.format("yyyyMMdd_k...
+ ".jpg";
mDialog = new Dialog(this);
mDialog.setContentView(R.layout.dialog);
mDialog.setTitle(getString(R.string.save_...
Button button;
button = (Button) mDialog.findViewById(R....
button.setOnClickListener(this);
button = (Button) mDialog.findViewById(R....
button.setOnClickListener(this);
TextView tv;
tv = (TextView) mDialog.findViewById(R.id...
tv.setText(mFileName);
tv = (TextView) mDialog.findViewById(R.id...
tv.setText(mWSize.getText().toString() + ...
+ mHSize.getText().toString());
mDialog.show();
}
}
private void execSave() {
int w = Integer.parseInt(mWSize.getText().toStr...
int h = Integer.parseInt(mHSize.getText().toSt...
Bitmap bitmap = Bitmap.createScaledBitmap(mBit...
try {
MediaStore.Images.Media.insertImage(getCo...
mFileName, null);
Toast.makeText(this, getString(R.string.s...
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, getString(R.string.s...
Toast.LENGTH_SHORT).show();
}
}
private Bitmap getImage(Uri uri) {
try {
InputStream is = getContentResolver().ope...
return BitmapFactory.decodeStream(is);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private void setPreview() {
if (mBitmap != null) {
mOrgW = mBitmap.getWidth();
mOrgH = mBitmap.getHeight();
mWSize.setText(String.valueOf(mOrgW));
mHSize.setText(String.valueOf(mOrgH));
mPreview.setImageBitmap(mBitmap);
}
}
}
~
-リスト3-14 controller.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/SelectImage"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/select_image" />
<Button
android:id="@+id/TakePhoto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/take_photo" />
<LinearLayout
android:id="@+id/WLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/WLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_w" />
<EditText
android:id="@+id/WSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/WSuffix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="px" />
</LinearLayout>
<LinearLayout
android:id="@+id/HLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip" >
<TextView
android:id="@+id/HLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_h" />
<EditText
android:id="@+id/HSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number" >
</EditText>
<TextView
android:id="@+id/HSuffix"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="px" />
</LinearLayout>
<CheckBox
android:id="@+id/KeepRatio"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:checked="true"
android:text="@string/keep_ratio" />
<Button
android:id="@+id/Save"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:text="@string/save" />
</LinearLayout>
~
-リスト3-15 layout/main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/Preview"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_margin="5dip"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
layout="@layout/controller" />
</LinearLayout>
~
-リスト3-16 layout-land/main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/Preview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="5dip"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="fitCenter" />
<include
android:layout_width="wrap_content"
android:layout_height="fill_parent"
layout="@layout/controller" />
</LinearLayout>
~
-リスト3-17 dialog.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/...
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/FileNameLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/FileLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/filename_label" />
<TextView
android:id="@+id/FileName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<LinearLayout
android:id="@+id/ImageSizeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip" >
<TextView
android:id="@+id/SizeLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/isize_label" />
<TextView
android:id="@+id/ImageSize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_weight="1" />
</LinearLayout>
<TextView
android:id="@+id/Description"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginRight="5dip"
android:gravity="right"
android:text="@string/save_desc" />
<LinearLayout
android:id="@+id/ButtonLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip"
android:gravity="center_horizontal" >
<Button
android:id="@+id/ExecSave"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/save" />
<Button
android:id="@+id/Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cancel" />
</LinearLayout>
</LinearLayout>
~
-リスト3-18 AndroidManifest.xml :
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/...
package="com.beatcraft.iresizer"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="7" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:configChanges="orientation"
android:label="@string/app_name"
android:name=".IResizerActivity" >
<intent-filter >
<action android:name="android.intent.act...
<category android:name="android.intent.c...
</intent-filter>
<intent-filter >
<category android:name="android.intent.c...
<data android:mimeType="image/*" />
<action android:name="android.intent.act...
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.WR...
</manifest>
~
----
RIGHT:内藤
ページ名:
BC::labsへの質問は、bc9-dev @ googlegroups.com までお願い致します。