
絶賛Androidの勉強中。
Wonderfl APIから情報を取ってきて表示しています。
今回は、
- JSONの扱い方
- ListViewのカスタマイズ
- ProgressDialogを使う
- AsyncTaskでバックグラウンド処理
の4つの勉強。
ちゃんとJSONパーサーがあるのでデータの解析は楽ですね。
各アイテムをクリックするとWonderflのサイトへ飛ぶようになってます。
以下、今回のソースです。
Main.java。
package jp.sakef;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
public class Main extends Activity
{
private int count;
private int numCode;
private ProgressDialog dialog;
private List<CodeData> list;
private ListView view;
// Activity作成時に実行
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.main);
// ListViewを取得
view = (ListView)findViewById(R.id.listView);
// ProgressDialogを作成
dialog = new ProgressDialog(this);
dialog.setTitle("Wonderflに接続中");
dialog.setMessage("Wonderflからsakefのデータを取得しています。");
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setCancelable(true);
dialog.show();
try
{
// Wonderflに接続
String key = "ここにAPI Keyを入れるのよー。";
String user = "sakef";
String url = "http://api.wonderfl.net/user/"+user+"/codes?api_key="+key;
HttpGet get = new HttpGet( url );
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get);
// 接続が成功しているか確認
int status = response.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) throw new Exception("Error!");
// 結果を取得
String source = EntityUtils.toString( response.getEntity());
JSONObject json = new JSONObject(source);
// statがokなら続行
count = 0;
list = new ArrayList<CodeData>();
String stat = json.getString("stat");
if(stat.equals("ok"))
{
JSONArray codes = json.getJSONArray("codes");
numCode = codes.length();
for(int i = 0; i < numCode; i++)
{
JSONObject code = codes.getJSONObject(i);
String title = code.getString("title");
String thm = code.getString("thumbnail");
String id = code.getString("id");
new ImageLoadTask(this, title, id).execute(thm);
}
}
else dialog.dismiss();
// 接続を解除
client.getConnectionManager().shutdown();
}
catch (ClientProtocolException e){Log.d("ClientProtocolException", e.getMessage());}
catch (IOException e){Log.d("IOException", e.getMessage());}
catch(Exception e){Log.d("Exception", e.getMessage());}
}
// 画像をロードするクラス
public class ImageLoadTask extends AsyncTask<String, Integer, Bitmap>
{
private Main parent;
private String title;
private String id;
// コンストラクタ
public ImageLoadTask(Activity activity, String title, String id)
{
parent = (Main)activity;
this.title = title;
this.id = id;
}
// 画像のロード
protected Bitmap doInBackground(String... args)
{
Bitmap bitmap = null;
try
{
URL url = new URL(args[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream in = new BufferedInputStream(conn.getInputStream());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] w=new byte[1024];
while (true)
{
int ss=in.read(w);
if (ss<=0) break;
bos.write(w,0,ss);
};
bitmap = BitmapFactory.decodeByteArray(bos.toByteArray(), 0, bos.size());
in.close();
bos.close();
conn.disconnect();
}
catch (Exception e){Log.d("Exception", e.getMessage());}
return bitmap;
}
// ロード終了後に実行
protected void onPostExecute(Bitmap result)
{
synchronized (parent)
{
count ++;
list.add(new CodeData(result, title, id));
if(count == numCode)
{
dialog.dismiss();
DataAdapter adapter = new DataAdapter(parent, R.layout.list_item, list);
view.setAdapter(adapter);
view.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String url = "http://wonderfl.net/c/"+list.get(position).id;
Uri uri=Uri.parse(url);
Intent intent=new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});
}
}
}
}
// リスト用のデータを保持するクラス
public class CodeData
{
public Bitmap bitmap;
public String title;
public String id;
public CodeData(Bitmap bitmap, String title, String id)
{
this.bitmap = bitmap;
this.title = title;
this.id = id;
}
}
// データをリストの表示させるためのアダプター
public class DataAdapter extends ArrayAdapter<CodeData>
{
private LayoutInflater inflater;
private List<CodeData> items;
public DataAdapter(Context context, int textViewResourceId, List<CodeData> objects)
{
super(context, textViewResourceId, objects);
items = objects;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public View getView(int position, View convertView, ViewGroup parent)
{
CodeData item = items.get(position);
View v = convertView;
if(v == null) v = inflater.inflate(R.layout.list_item, null);
ImageView iv = (ImageView)v.findViewById(R.id.img);
iv.setImageBitmap(item.bitmap);
TextView tv = (TextView)v.findViewById(R.id.text);
tv.setText(item.title);
return v;
}
}
}
main.xml。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/mainLayout"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false"/>
</LinearLayout>
list_item.xml。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id = "@+id/listLayout"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding = "10px"
android:background = "#000000">
<ImageView
android:id = "@+id/img"
android:width = "140px"
android:height = "140px"
android:paddingRight = "20px"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:scaleType = "fitXY" />
<TextView
android:id = "@+id/text"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_marginTop = "20px"
android:textSize = "15px"
android:width = "200px"
android:textColor = "#FFFFFF" />
</LinearLayout>