FC2ブログ
ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »画像ファイル読み込み
このページの記事一覧

【Java】【Android】【PHP】画像を PHP から送信して、Android で受信する  


 以前に、JSON (テキストデータ) を PHP から送信して、Java で受け取ることができたので、今回はそれと同じ考え方で、画像の送受信に置き換えてみる。わざわざ PHP を通してダウンロードしているわけだが、もちろん直接画像のURLにアクセスしてダウンロードしても構わない。PHP でダウンロードする利点はファイル名をデータベースなどに入れて置いて、同じURLで内容を入れ替えられる点だ。この方法なら、画像ファイルを直接アクセスできない場所に置いて、ファイル自体を隠蔽化することもできる。

 クライアント側は Java にしたいので、とりあえず Android にする。画像のデコードはプラットフォームごとに異なるので、その部分だけ入れ替えれば、流用もできるだろう。


 PHP のサンプルコードは超絶簡単なものにする。エラーなどはあまり考えてないので、必要なら適当に付け加えた方が良いだろう。とりあえずファイル名を「image_out.php」としておく。

■画像送信用 PHP(image_out.php)
<?php
$fileName = "img/sample.jpg"; //ファイル名

if (file_exists($fileName)) {
header('Content-type: image/jpeg');
header('Content-Length: '.filesize($fileName)); //あった方が良い
readfile($fileName); //ファイルを読み込んで標準出力に書き出し
exit;
}
?>

 header() で Content-type を出力してるので、「<?php」タグより以前に文字列などを書かないように注意。改行1つでも入ると、PHP では text/html として出力されてしまう。

 このサンプルの場合は、画像ファイル名が固定されているので Content-type が固定されているが、データベースなどからファイル名を読み込んで、画像を切替える場合は、拡張子などで Content-type を切り替えるようにした方が良いだろう。

 ちなみに png と gif の Content-type は、
header('Content-Type: image/png');
header('Content-Type: image/gif');

となる。また、Android では gif はサポート対象外なので、あまり使わない方が良いかも知れない。透過したい場合は png が良いだろう。

 一緒に Content-Length も出力しているが、画像ファイルの場合はあった方が良い。ないと以下の Java コードで Content-Length = -1 (不明)となる。あらかじめファイルサイズを取得して、縮小してダウンロードするときなどには必要になるだろう。ちなみにテキストファイル(text/plain)の場合はコードを書かなくても、Content-Length は勝手に付いてくる(書いても問題ない)。


 あとは、Android 側で画像の受信とデコードをする。以前の JSON 用コードとあまり変わらないので、目新しいものは無いかも知れない。また、Android の場合、マニフェストファイル(AndroidManifest.xml)にインターネット接続用のパーミッションが必要になる。

■インターネット接続用のパーミッション(AndroidManifest.xml)
<uses-permission android:name="android.permission.INTERNET" />

■画像受信用 Java (Android 用)
//テストのメイン... (※例外処理は簡略)
final int CONNECT_TIMEOUT = 15 * 1000; //接続タイムアウト[ms]

String phpUrl = "http://(テストするサーバー)/image_out.php"; //画像送信用 PHPのURL

Bitmap bitmap = null; //受信した画像を入れる

try {
URL url = new URL(phpUrl);
HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setConnectTimeout(CONNECT_TIMEOUT); //接続タイムアウト
con.setRequestMethod("GET");
con.connect();

bitmap = BitmapFactory.decodeStream(con.getInputStream()); //画像デコード

//確認用
System.out.println("con.getContentType() = " + con.getContentType());
System.out.println("con.getContentLength() = " + con.getContentLength());
System.out.println("con.getResponseCode() = " + con.getResponseCode());
System.out.println("con.getResponseMessage() = " + con.getResponseMessage());

con.disconnect();

} catch (Exception e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}

// ・・・・
// onDraw() などで確認する場合
if (bitmap != null) {
canvas.drawBitmap(bitmap, 0, 0, null);
}

 例外処理はかなり手抜きしてるので、必要に応じて適当に。サーバー接続タイムアウトを取得したいなら、catch 節に SocketTimeoutException を加えれば、捕えることができる。

 URL は HttpURLConnection を使ってるので「http://」前提だが、「https://」なら、HttpsURLConnection を使った方が良いかも知れない(テスト環境がないので、やったことない)。

 また本来なら、サーバーのレスポンスも考慮に入れて、ネットからのダウンロード等は別スレッドでやった方が良いだろう。Android なら ServiceAsyncTask がよく使われているようだ。


(関連記事)
【Java】【PHP】【JSON】JSON を PHP から送信して、Java で受信する
【Java】【PHP】【JSON】JSON を Java から送信して、PHP で受信する
【PHP】【Android】apk ファイルを PHP でダウンロードする


スポンサーサイト

category: Android

thread: プログラミング

janre: コンピュータ

tag: PHP  画像ファイル読み込み  通信 
tb: 0   cm: --

【Android】【Java】リソース名で、res/drawable-~ フォルダから、画像を読み込む(Drawable)  


もうひとつ、Android 特有の Drawable オブジェクトでも、「res/raw フォルダから、テキストファイルを読み込む」と同じように、リソース名を引数にした画像読み込み関数を書いておく。

//リソース名で、res/drawable-~ フォルダから、画像を読み込む(Drawable) (Android 用)
public static final Drawable loadDrawableResource(String resName, Context context) throws IOException, FileNotFoundException {
final int id = context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
if (id == 0) { //エラーにはならない
throw new FileNotFoundException("Not Found - " + resName);
}
return context.getResources().getDrawable(id);
}

//メインでは... (※例外処理は省略)
String resName = "sample"; //"res/drawable-nodpi/sample.jpg" 等
Drawable drawable = loadDrawableResource(resName, this); //this は起動した Activity が良い(Context)

例外処理は手抜きしてるので、必要に応じて適当に。

リソースIDで画像読み込みを行うならば、return 文の1行だけでも良い。

Drawable drawable = getContext().getResources().getDrawable(R.drawable.sample);

ただ、ファイル読み込みでは通常、String 型のファイル名等がほとんどなので、int 型のリソースID形式でコードを大量に書いてしまうと汎用性の面では劣る。例えば、リソースIDが割り振られない場所(assets フォルダ等)に移動したときなどは、コードの大幅修正が必要になる。後々の使い回しも考えてコーディングするなら、String 型のリソース名で書いておいた方が、修正も楽だろう。ファイル名やリソース名は設定ファイル等に書いておき、メインコードを interface などを噛ませて置けば、ほとんど修正しなくて良いという利点がある。そういうときに利用すると良い。

ちなみに、「drawable-nodpi」というフォルダを作って、画像を入れておくと、Drawable オブジェクト特有の端末の解像度による自動リサイズがされなくなり、元の画像サイズでロードされる。

実のところ、私はコードの互換性を考えて、ほとんど Drawable オブジェクトは使わない。しかし、画像の拡大・縮小が手軽にできるので、そのためだけに一時的に利用する事がある。そういうときも interface を噛ませておいて、必要に応じて、別仕様の入れ替えができるように作って置くと良いだろう。なるべくプラットフォーム特有仕様は、避ける工夫をしておいた方が、長い目で見れば有益な事が多い。


(関連記事)
【Android】リソース名で、res/drawable-~ フォルダから、画像を読み込む(Bitmap)
【Android】res/raw リソースフォルダからテキストファイルを読み込む
【Android】画像リソースIDをコードで取得する
【Android】アプリ名 app_name タグをコードで取得する
【Android】assets フォルダから画像ファイルを読み込む
【Android】SDカードから画像ファイルを読み込む
【Android】内部ストレージから画像ファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


category: Android

thread: プログラミング

janre: コンピュータ

tag: 画像ファイル読み込み 
tb: 0   cm: --

【Android】【Java】リソース名で、res/drawable-~ フォルダから、画像を読み込む(Bitmap)  


ついでなので、「res/raw フォルダから、テキストファイルを読み込む」と同じように、リソース名を引数にした画像読み込み関数を書いておこう。

//リソース名で、res/drawable-~ フォルダから、画像を読み込む(Bitmap) (Android 用)
public static final Bitmap loadBitmapResource(String resName, Context context) throws IOException, FileNotFoundException {
final int id = context.getResources().getIdentifier(resName, "drawable", context.getPackageName());
if (id == 0) { //エラーにはならない
throw new FileNotFoundException("Not Found - " + resName);
}
return BitmapFactory.decodeResource(context.getResources(), id);
}

//メインでは... (※例外処理は省略)
String resName = "sample"; //"res/drawable-nodpi/sample.jpg" 等
Bitmap bitmap = loadBitmapResource(resName, this); //this は起動した Activity が良い(Context)

例外処理は手抜きしてるので、必要に応じて適当に。

リソースIDで画像読み込みを行うならば、return 文の1行だけでも良い。

Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.sample);

ただ、ファイル読み込みでは通常、String 型のファイル名等がほとんどなので、int 型のリソースID形式でコードを大量に書いてしまうと汎用性の面では劣る。例えば、リソースIDが割り振られない場所(assets フォルダ等)に移動したときなどは、コードの大幅修正が必要になる。後々の使い回しも考えてコーディングするなら、String 型のリソース名で書いておいた方が、修正も楽だろう。ファイル名やリソース名は設定ファイル等に書いておき、メインコードを interface などを噛ませて置けば、ほとんど修正しなくて良いという利点がある。そういうときに利用すると良い。


(関連記事)
【Android】リソース名で、res/drawable-~ フォルダから、画像を読み込む(Drawable)
【Android】res/raw リソースフォルダからテキストファイルを読み込む
【Android】画像リソースIDをコードで取得する
【Android】アプリ名 app_name タグをコードで取得する
【Android】assets フォルダから画像ファイルを読み込む
【Android】SDカードから画像ファイルを読み込む
【Android】内部ストレージから画像ファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


category: Android

thread: プログラミング

janre: コンピュータ

tag: 画像ファイル読み込み 
tb: 0   cm: --

【Android】【Java】内部ストレージから画像ファイルを読み込む  


 これも基本は「内部ストレージからテキストファイルを読み込む」と同じ。変更点はストリームを開いた後のデコーダーを、画像用に書き換えれば良いだけ。

//内部ストレージから、画像ファイルを読み込む(Android 用)
public static final Bitmap loadBitmapLocalStorage(String fileName, Context context)
throws IOException, FileNotFoundException {
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(context.openFileInput(fileName));
return BitmapFactory.decodeStream(bis);
} finally {
try {
bis.close();
} catch (Exception e) {
//IOException, NullPointerException
}
}
}


//メインでは... (※例外処理は省略)
String fileName = "sample.jpg"; // "data/data/[パッケージ名]/files/sample.jpg" になる
Bitmap bitmap = loadBitmapLocalStorage(fileName, this); //this は起動した Activity が良い(Context)

 例外処理は手抜きしてるので、必要あれば適当に。

 DDMS で覗いて、保存フォルダが作られていれば、右上の方にある [push] ボタンからファイル転送もできるが、無い場合は、Context クラスの openFileOutput() で書き込めばフォルダが自動的に作られる。


(関連記事)
【Android】内部ストレージに画像ファイルを保存する(png)
【Android】内部ストレージに画像ファイルを保存する(jpg)
【Android】内部ストレージからテキストファイルを読み込む
【Android】内部ストレージにテキストファイルを保存する
【Android】SDカードから画像ファイルを読み込む
【Android】assets フォルダから画像ファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


category: Android

thread: プログラミング

janre: コンピュータ

tag: 画像ファイル読み込み  内部ストレージ 
tb: 0   cm: --

【Android】【Java】SDカードから画像ファイルを読み込む  


 これも基本は「SDカードからテキストファイルを読み込む」と同じ。変更点はストリームを開いた後のデコーダーを、画像用に書き換えれば良いだけ。

 isMountSDCard(), toSDCardAbsolutePath() は以前に作ったものを、そのまま使えば良い。
(※) Android4.4(API 19)あたりから内部ストレージの仮想パスに変わった模様
// SDCard のマウント状態をチェックする(Android 用)
public static final boolean isMountSDCard() {
final String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true; //マウントされている
} else {
return false; //マウントされていない
}
}

// SDCard のルートディレクトリを取得(Android 用)
public static final File getSDCardDir() {
return Environment.getExternalStorageDirectory();
}

// SDCard 内の絶対パスに変換(Android 用)
public static final String toSDCardAbsolutePath(String fileName) {
return getSDCardDir().getAbsolutePath() + File.separator + fileName;
}


//SDCard から、画像ファイルを読み込む(Android 用)
public static final Bitmap loadBitmapSDCard(String fileName) throws IOException {
if (!isMountSDCard()) {
throw new IOException("No Mount");
}
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(new FileInputStream(toSDCardAbsolutePath(fileName)));
return BitmapFactory.decodeStream(bis);
} finally {
try {
bis.close();
} catch (Exception e) {
//IOException, NullPointerException
}
}
}


//メインでは... (※例外処理は省略)
String fileName = "sample.jpg"; //"mnt/sdcard/sample.jpg" or "sdcard/sample.jpg" 等になる(端末による)
Bitmap bitmap = loadBitmapSDCard(fileName);

 例外処理は手抜きしてるので、必要あれば適当に。

 SDカードは基本的にマウント状態等のデバイス特有処理以外は、通常のローカルシステムのファイル処理と変わらないので、実は応用は非常に簡単。


(関連記事)
【Android】SDカードに画像ファイルを保存する(png)
【Android】SDカードに画像ファイルを保存する(jpg)
【Android】SDカードからテキストファイルを読み込む
【Android】SDカードにテキストファイルを保存する
【Android】SDカードのファイルを削除する
【Android】assets フォルダから画像ファイルを読み込む
【Android】内部ストレージから画像ファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


category: Android

thread: プログラミング

janre: コンピュータ

tag: 画像ファイル読み込み  SDカード 
tb: 0   cm: --


プロフィール

Social

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop