突然ですが、PC向けのWebサービスを作ってきた僕にとって通信状況を気にしなければいけないというのはかなり新鮮でした。
Androidのアプリケーション(特に通信を必要とするアプリケーション)を開発する上で知っておきたい、ネットワークの状況を知る方法をメモしておきます。
public boolean isNetworkEnable(Context context){
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
// モバイル回線(3G)の接続状態を取得
State mobile = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();
// wifiの接続状態を取得
State wifi = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();
// 3Gデータ通信/wifi共に接続状態じゃない場合
if ( (mobile != State.CONNECTED) && (wifi != State.CONNECTED) ) {
// ネットワーク未接続
return false;
}else{
return true;
}
}
こんなメソッドを実装してしまえば通信できる状況かどうかを簡単にアプリケーションから取得できるようになると思います。当初Wifiでの通信状況をきちんと加味しないでいたので若干ハマったので気をつけてみてください。
前回画像のURLからBitmapを生成する簡単な方法をまとめましたが、一度ダウンロードした画像を端末にキャッシュして通信を減らすことをしてみます。
画像をよく扱うアプリを作る場合(しかも見られる頻度が高い画像が多い場合)結構効果的です。
import java.lang.ref.SoftReference;
import java.util.HashMap;
import android.graphics.Bitmap;
public class ImageCache {
private static HashMap<String,SoftReference<Bitmap>> cache = new HashMap<String,SoftReference<Bitmap>>();
public static Bitmap getImage(String key) {
if (cache.containsKey(key)) {
SoftReference<Bitmap>ref = cache.get(key);
if (ref != null) {
return ref.get();
}
}
return null;
}
public static void setImage(String key, Bitmap image) {
cache.put(key, new SoftReference<Bitmap>(image));
}
public static boolean hasImage(String key) {
return cache.containsKey(key);
}
public static void clear() {
cache.clear();
}
}
SoftReferenceを使えば適切にガベージコレクトしてくれるし、お手軽にキャッシュが実装できると思います。
今回の場合はURLをキーに画像のBitmapを値にしてHashMapを作ってそこでキャッシュしています。
前回の記事とあわせてキャッシュを実装した画像ダウンロードのメソッドが下のような感じです。
public Bitmap getImage(src){
try{
ImageCache cache = new ImageCache();
Bitmap img = ImageCache.getImage(src);
if(img != null){
return img;
}else{
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
cache.setImage(src, myBitmap);
return myBitmap;
}
} catch (OutOfMemoryError e) {
//画像が大きすぎたりする場合
e.printStackTrace();
return null;
} catch (Exception e){
e.printStackTrace();
return null;
}
}
Webにある画像を取り扱うAndroidアプリの開発をする場合、画像のURLからBitmapを生成するという処理が必須だと思います。
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
} catch (OutOfMemoryError e) {
//画像が大きすぎたりする場合
e.printStackTrace();
} catch (Exception e){
e.printStackTrace();
return null;
}
HttpURLConnectionとBitmapFactory.decodeStreamを使えばシンプルですね。
このBitmapをImageViewのsetImageBitmapなどで設定して上げれば画面に取得してきた画像を表示できます。
OutOfMemoryErrorの例外をキャッチしてあげるとより安全だと思います。
次回は一度取得した画像をキャッシュして、高速化する方法を紹介します。
お久しぶりです。
少し近況報告から行きます。
最近まで主にRuby on Railsを用いたWebAPIの開発、Solrを利用した検索システムの開発、ImageMagickを利用した画像処理の仕事をしていましたが、3月からAndroidアプリの開発者として新たなスタートを切りました。
ベンチャー企業に転職して3月で丸一年、数々の失敗も重ねましたが自分の中では未体験の事ばかりだったので得た物はかなり多かったように思います。
去年の年末、次のステップとして何をすべきか考えていました。
チームの為、自分の為に何をするのがいいのかを考えたとき自分の中で見つけた答えがAndroidアプリの開発でした。
もともと(今でも)iPhoneユーザですし、Androidに対して特別な思いがあったわけでもありませんでしたが、会社にAndroidの開発をやる人がいなかったこと(iOSアプリの開発をしている先輩がAndroidアプリ開発もできるという状態)、自分のスキルとして今までなかったことをやりたかったのが大きな理由でした。
いきなり今までの仕事からきっぱり離れるのは無理ですが、少しずつAndroidアプリの開発者としてインプットとアウトプットを続けて行きたいと思います。これから失敗もたくさんするでしょうが、恐れずに進んでいきたいと思います。