素人のアンドロイドアプリ開発日記

通信のコンテンツ

非同期での読み込みクラスを作りました。JSON,TEXTなど

2012.02.16

通信関連がちょっとめんどうくさかったので、自分で使うようにクラスを作りましたので、よかったらお使いください。

使い方は

JsonLoader task = new JsonLoader();
 task.setOnCallBack(new CallBackJson(){
 @Override
 public void CallBack(String Result) {
 Toast.makeText(TopActivity.this, Result, 800).show();
 };
 });
 task.execute(RSS_FEED_URL);

RSS_FEED_URLっていうのが、URLです。そんで、CallBackと言うのが読み込みが完了した時に出力される内容です。Resultに読み込んだデータがStringで入っています。

あんまり複雑じゃない仕様にしました。

 

2つのクラスから構成しています。

・CallBackJson

・JsonLoader

です。JSONの読み込み用に作ったので、JSONってつけましたが、XMLもテキストとしてだったら読み込みができるかと思います。

java.net.UnknownHostException

なエラーが出た場合には、いろいろ問題があった時ですが、パーミッションの可能性もあります。

<uses-permission android:name="android.permission.INTERNET"></uses-permission>

webViewを使わないとたまに見落としてしまいます。

 

以下ソースです。

・CallBackJson

package ***;

public class CallBackJson {
 
 public void CallBack(String Result){
 //ここにいろいろ関数をかけばいいと思う。(上書きされる部分)
 }
}

・JsonLoader

package ***;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.os.AsyncTask;
import android.widget.Toast;

public class JsonLoader extends AsyncTask<String, Integer, String> {
 
 private CallBackJson callbackjson;
 
 // コンストラクタ  
 public JsonLoader() {}
 
 @Override  
 protected void onPreExecute() {}

 @Override
 protected String doInBackground(String... params) {
 String _str= getData(params[0]);
 return _str;
 }
 
 public void setOnCallBack(CallBackJson _cbj){
 callbackjson = _cbj;
 }
 
 @Override  
 protected void onPostExecute(String result) {
 callbackjson.CallBack(result);
 }  
 
 public String getData(String _url) {
 DefaultHttpClient objHttp = new DefaultHttpClient();
 HttpParams params = objHttp.getParams();  
 HttpConnectionParams.setConnectionTimeout(params, 3000);
 HttpConnectionParams.setSoTimeout(params, 3000);
 String _return = "";  
 
 try {  
 HttpGet objGet   = new HttpGet(_url);  
 HttpResponse objResponse = objHttp.execute(objGet);  
 if (objResponse.getStatusLine().getStatusCode() < 400){  
 InputStream objStream = objResponse.getEntity().getContent();  
 InputStreamReader objReader = new InputStreamReader(objStream);  
 BufferedReader objBuf = new BufferedReader(objReader);  
 StringBuilder objJson = new StringBuilder();  
 String sLine;
 while((sLine = objBuf.readLine()) != null){  
 objJson.append(sLine);  
 }  
 _return = objJson.toString();  
 objStream.close();  
 }  
 } catch (IOException e) { 
 return e.toString();
 } 
 
 return _return;  
 }
}

これは非同期で読んでくれるので、割と使いやすいかと思います。どぞどぞ、お使いください。

 

 

■追記

callbackjson = null;

をonPostExcuteの中に入れてメモリを解放してあげる必要がありました。

カテゴリー:通信

JSONのデータをパースしてみる。

2011.11.16

前回、JSONのデータを表示したのですが、Stringで表示しても利用が出来ないかと思います。

 

JSONの読み込みをしたい!

 

今回はJSONのデータをパースと言う方法を用いて、個別に扱いたいと思います。今回もtwitterのJSONを読み込んでみたいです。

JSONをパース(解析)する | Tech Booster

上記のサイトがとてもまとまっていました。

が、前回のtwitterをパースしようとしたら、ちょっとだけうまく行かない部分があったので、下記のように変更しました。(twitterのJSONだからかもしれません。)

まず、dataをJSONArrayにパースをします。(tech boosterの場合、JSONObjectにしていました。)

try {
 JSONArray _jsonArr = new JSONArray(result);
 } catch (JSONException e) {
 // TODO Auto-generated catch block
 e.printStackTrace();
 }

 

その配列の中から、”text”要素を取り出します。(ここはただの配列と同様です。)

for (int i = 0; i < _jsonArr.length(); i++) {
 JSONObject jsonObject = _jsonArr.getJSONObject(i);
 Log.d("look",jsonObject.getString("text"));
 }

 

Logで出力すると下記のようになりました。勝手にlookとかつけてしまったのですが、そこは好きな言葉で大丈夫です。

Twitter

※僕のツイッターのツイートです。。

 

これでJSONの値の取得ができるようになりました!もしこの方法でダメな場合はTech Boosterさんの方でやればいいと思います。

 

 

カテゴリー:通信

JSONの読み込みをしたい!

2011.11.16

JSONの読み込みの勉強をしたいと思います。

最近では、xmlよりもjsonが使われる事もずいぶん多くなった気がします。

自分では感じる事はそんなにないのですが、サイズなども軽いようです。

また形式的には、objectに近いので、扱いやすいと言う点が上げられるようです。

 

まずは、読み込みの処理なのでマニフェストにINTERNETを追加します。

<uses-permission android:name="android.permission.INTERNET"/>

 

次に読み込みの際には、androidのthread構造の為、他の動作がとまってしまう→ローディングが動かない。と言う症状を回避する為に、asyncTaskのクラスを作成します。

asyncTaskに関しては、3つの引数が設定できるのですが、呼び出し元のクラスを参照したいので、そのactivityとあとは適当にstringを設定してみました。

public class JsonLoader extends AsyncTask<String,TestActivity, String> {
 TestActivity _teAct;
 // コンストラクタ  
 public JsonLoader(String _str1,teActivity activity, String _str2) {  
 _teAct = activity;
 }

コンストラクタで、呼び出し元のactivityを参照できました(もちろん呼び出し元からの設定も必要ですが。。)

また、asyncTaskで、は「はじめ」「実行」「終わり」実装ができるので、はじめに、ローディングの設定をして終わりにローディングをけしましょう。

はじめ

@Override  
 protected void onPreExecute() {  
 // プログレスバーを表示する  
 _pd = new ProgressDialog(_teAct);  
 _pd.setMessage("Now Loading...");  
 _pd.show();  
 }

おわり

// メインスレッド上で実行される  
 @Override  
 protected void onPostExecute(String result) {  
 _pd.dismiss();  
 Toast.makeText(_teAct,result,Toast.LENGTH_LONG).show();
 }

終わりの時には読み取った値をToastで表示できるようにしました。

また、実行に際してですが、JSONの読み込みは下記を参考にさせていただきました。

【Android開発】HttpClientとHttpGetでサーバーとjson通信する|SE奮闘気

ここで紹介されているgetDataと言うクラスです。

/** 
 * 指定URLからgetした文字列を取得する 
 * @param sUrl 
 * @return 
 */  
 public String getData(String sUrl) {  
 HttpClient objHttp = new DefaultHttpClient();  
 HttpParams params = objHttp.getParams();  
 HttpConnectionParams.setConnectionTimeout(params, 1000); //接続のタイムアウト  
 HttpConnectionParams.setSoTimeout(params, 1000); //データ取得のタイムアウト  
 String sReturn = "";  
 try {  
 HttpGet objGet   = new HttpGet(sUrl);  
 HttpResponse objResponse = objHttp.execute(objGet);  
 if (objResponse.getStatusLine().getStatusCode() < 400){  
 InputStream objStream = objResponse.getEntity().getContent();  
 InputStreamReader objReader = new InputStreamReader(objStream);  
 BufferedReader objBuf = new BufferedReader(objReader);  
 StringBuilder objJson = new StringBuilder();  
 String sLine;  
 while((sLine = objBuf.readLine()) != null){  
 objJson.append(sLine);  
 }  
 sReturn = objJson.toString();  
 objStream.close();  
 }  
 } catch (IOException e) {  
 return null;  
 }     
 return sReturn;  
 }

この中にToastを入れて値を確認しようとして失敗しました。(使っちゃダメみたいです。。)

これを用いて実行のフェーズは次のようにしました。

@Override
 protected String doInBackground(String... params) {
 String _str= getData(params[0]);
 return _str;
 }

これで、jsonのファイルを読み込んで、Toastで表示をするasyncTaskの完成です。

 

上記をメインのクラスから呼ぶ時は以下の形です。

public static final String RSS_FEED_URL = "http://api.twitter.com/1/statuses/user_timeline/shunjiro.json";
// タスクを起動する  
 JsonLoader task = new JsonLoader("" ,this,"");  
 task.execute(RSS_FEED_URL);

※すいません。僕のツイートを呼んでいます。

今回はJSONのデータをそのままStringで取得を行いました。次回は、この値をパースできるように勉強したいと思います。

 

カテゴリー:通信

ASCII.jpでIntentの復習

2011.04.04

asciiさんの記事でintentについての記載があったので、

復習に使わせていただきました。

■INTENTで設定画面に移動する。

Intent intent = new Intent(Settings.ACTION_DATE_SETTINGS);
startActivity(intent);

と設定すると設定画面に移動ができる。ここの値で、アンドロイドで設定している電話や、webブラウザー、地図、音楽プレイヤーなどを呼び出せる。

■INTENTで他のクラスに移動をする。

Intent intent = new Intent(this,***.class);

として「コンストラクタは自分自身と呼び出し先となるクラス名」なので、簡単にできました。

移動先では、returnIntentと言うクラスが勝手にできるようで(未確認)

※上記できませんでした。自分で作成をする必要があります。

任意で戻る場合

setResult(RESULT_OK, returnIntent);
finish();

戻るボタンなどで、戻る場合

returnIntent = new Intent();
setResult(RESULT_CANCELED, returnIntent);

上記のようになる。
この値は戻り先でも利用できる為、戻り方を調べる事ができる。
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
 super.onActivityResult(requestCode, resultCode, data);
 if (resultCode == RESULT_OK) {
 if (requestCode == R.id.IntentRequestGeneral ){
 String returnMessage = data.getStringExtra(this.getString(R.string.ExtraString01));
 message.setText(this.getString(R.string.MainDispString)+" " +returnMessage);
 }
 }
 else {
 Toast.makeText(this, "onActivityResult NOT RESULT_OK", Toast.LENGTH_SHORT).show();
 }
}

どうやら、リクエストコードとは、アクティビティを結びつけてどのアクティビティからの戻りなのか、確認できるようである。

※訂正 上記が自動で帰ってくると認識していましたが、インテント発行をstartActivityでした場合にはResultのイベントは実行されないので、resultでイベントを受け取りたい場合にはstartActivityForResultで他のIntentに移動しておく必要がありました。

逆引きandroid入門さんでは、REQUEST_CODEを一緒に発行できるようだ。

// インテント発行
startActivityForResult(intent, REQUEST_CODE);

以上で簡単にintentにREQUEST_CODEを含んだ状態で発行する事で、コードとアクティビティを結びつける事ができた。

カテゴリー:通信

RSSリーダーを作成する。ファイル一式

2011.04.01

今回は、外部サイトITproさんの記事を読んで、RSSリーダーを作成しました。

RSSリーダーを作成する。リストビューとItemを作成

RSSリーダーを作成する。xmlとかをパースする。

RSSリーダーを作成する。詳細画面を表示する。

今回は上記のそうまとめ作成ファイルをまとめさせていただきまして

次のような形で表示がされました。

rss1

クリック時

rss2

ファイル名には大文字をつけてはいけないと今回しりました。。

ファイル:main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 >
<ListView android:layout_height="wrap_content" 
 android:id="@+id/listView1" android:layout_width="fill_parent"></ListView>
</LinearLayout>

ファイル:itemlayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:orientation="vertical">
 <TextView 
 android:text="TextView" 
 android:id="@+id/textView1" 
 android:textColor="#ffffff"
 android:lines="1"
 android:textSize="18sp"
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content"></TextView>
 <TextView 
 android:text="TextView" 
 android:id="@+id/textView2" 
 android:lines="2"
 android:ellipsize="end"
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content"></TextView>
</LinearLayout>

ファイル:item_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 <TextView 
 android:text="TextView" 
 android:id="@+id/textView1" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content"></TextView>
 <TextView 
 android:text="TextView" 
 android:id="@+id/textView2" 
 android:layout_width="wrap_content" 
 android:layout_height="wrap_content"></TextView>
</LinearLayout>

ファイル:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="in.andante.rssReads"
 android:versionCode="1"
 android:versionName="1.0">
 <uses-sdk android:minSdkVersion="7" />
 <uses-permission android:name="android.permission.INTERNET"></uses-permission>

 <application android:icon="@drawable/icon" android:label="@string/app_name">
 <activity android:name=".rssReads"
 android:label="@string/app_name">
 <intent-filter>
 <action android:name="android.intent.action.MAIN" />
 <category android:name="android.intent.category.LAUNCHER" />
 </intent-filter>
 </activity>
 <activity
 android:name=".ItemDetailActivity">
 </activity>
 </application>
</manifest>

ファイル:rssReads.java

package in.andante.rssReads;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

public class rssReads extends Activity implements OnItemClickListener{
 public static final String RSS_FEED_URL = "http://andante.in/i/feed/";
 private ArrayList mItems;
 private RssListAdapter mAdapter;
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.main);

 mItems = new ArrayList();
 mAdapter = new RssListAdapter(this, mItems);

 ListView _listview = (ListView)findViewById(R.id.listView1);

 //_listview.setAdapter(mAdapter);

 // タスクを起動する
 RssParserTask task = new RssParserTask(this, mAdapter,_listview);
 task.execute(RSS_FEED_URL);
 _listview.setOnItemClickListener(this);

 // サンプル用に空のItemオブジェクトをセットする
 /*for (int i = 0; i < 10; i++) {
 mAdapter.add(new Item());
 }*/
 }

 @Override
 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
 // TODO Auto-generated method stub
 Item item = (Item)mItems.get(arg2);
 Intent intent = new Intent(this, ItemDetailActivity.class);
 intent.putExtra("TITLE", item.getTitle());
 intent.putExtra("DESCRIPTION", item.getDescription());
 startActivity(intent);
 }

}

ファイル:Item.java

package in.andante.rssReads;

public class Item {
 private CharSequence mTitle;
 private CharSequence mDescription;

 public Item(){
 mTitle = "";
 mDescription="";
 }

 public CharSequence getDescription(){
 return mDescription;
 }

 public void setDescription(CharSequence description){
 mDescription = description;
 }

 public CharSequence getTitle(){
 return mTitle;
 }

 public void setTitle(CharSequence title){
 mTitle = title;
 }

}

ファイル:RssListAdapter.xml

package in.andante.rssReads;

import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class RssListAdapter extends ArrayAdapter<Item> {

 private LayoutInflater mInflater;
 private TextView mTitle;
 private TextView mDescr;

 public RssListAdapter(Context context, List<Item> objects) {
 super(context,0, objects);
 // TODO Auto-generated constructor stub
 mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 }

 //一行ごとのビューを作成する。
 public View getView(int position, View convertView,ViewGroup parent){
 View view = convertView;
 if(convertView == null){
 view = mInflater.inflate(R.layout.itemlayout, null);
 }
 //何番目の値を取得?
 Item item = this.getItem(position);
 if(item != null){
 String title = item.getTitle().toString();
 mTitle = (TextView)view.findViewById(R.id.textView1);
 mTitle.setText(title);
 String descr = item.getDescription().toString();
 mDescr = (TextView)view.findViewById(R.id.textView2);
 mDescr.setText(descr);
 }
 return view;
 }
}

ファイル:RssParserTask.xml

package in.andante.rssReads;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.util.Xml;
import android.widget.ListView;

//RssParserTask.java
public class RssParserTask extends AsyncTask<String, Integer, RssListAdapter> {

 private rssReads mActivity;
 private RssListAdapter mAdapter;
 private ProgressDialog mProgressDialog;
 private ListView mListView;

 // コンストラクタ
 public RssParserTask(rssReads activity, RssListAdapter adapter,ListView _listView) {
 mActivity = activity;
 mListView = _listView;
 mAdapter = adapter;
 }

 // タスクを実行した直後にコールされる
 @Override
 protected void onPreExecute() {
 // プログレスバーを表示する
 mProgressDialog = new ProgressDialog(mActivity);
 mProgressDialog.setMessage("Now Loading...");
 mProgressDialog.show();
 }

 // バックグラウンドにおける処理を担う。タスク実行時に渡された値を引数とする
 @Override
 protected RssListAdapter doInBackground(String... params) {
 RssListAdapter result = null;
 try {
 // HTTP経由でアクセスし、InputStreamを取得する
 URL url = new URL(params[0]);
 InputStream is = url.openConnection().getInputStream();
 result = parseXml(is);
 } catch (Exception e) {
 e.printStackTrace();
 }
 // ここで返した値は、onPostExecuteメソッドの引数として渡される
 return result;
 }

 // メインスレッド上で実行される
 @Override
 protected void onPostExecute(RssListAdapter result) {
 mProgressDialog.dismiss();
 mListView.setAdapter(result);
 }

 // XMLをパースする
 public RssListAdapter parseXml(InputStream is) throws IOException, XmlPullParserException {
 //パーサーを作成する。
 XmlPullParser parser = Xml.newPullParser();
 try {
 //パーサーにinputStraemをセットする。これはURLを読み込んでいるStream
 parser.setInput(is, null);

 //読み込みの進捗をここから取得ができる。(値はSTARTなどが存在する。)
 int eventType = parser.getEventType();
 Item currentItem = null;
 while (eventType != XmlPullParser.END_DOCUMENT) {
 String tag = null;
 switch (eventType) {
 case XmlPullParser.START_TAG:
 tag = parser.getName();
 if (tag.equals("item")) {
 currentItem = new Item();
 } else if (currentItem != null) {
 if (tag.equals("title")) {
 //タイトルタグの中身の文字の事
 currentItem.setTitle(parser.nextText());
 } else if (tag.equals("description")) {
 //説明タグの中身の文字の事
 currentItem.setDescription(parser.nextText());
 }
 }
 break;
 case XmlPullParser.END_TAG:
 tag = parser.getName();
 if (tag.equals("item")) {
 mAdapter.add(currentItem);
 }
 break;
 }
 eventType = parser.next();
 }
 } catch (Exception e) {
 e.printStackTrace();
 }
 return mAdapter;
 }
}

ファイル:ItemDetailActivity.xml

package in.andante.rssReads;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class ItemDetailActivity extends Activity {
 private TextView mTitle;
 private TextView mDescr;

 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.item_detail);

 Intent intent = getIntent();

 String title = intent.getStringExtra("TITLE");
 mTitle = (TextView) findViewById(R.id.textView1);
 mTitle.setText(title);
 String descr = intent.getStringExtra("DESCRIPTION");
 mDescr = (TextView) findViewById(R.id.textView2);
 mDescr.setText(descr);

 }

}

以上で、お見苦しい部分もあるかと思いますが、お役に立てれば幸いです。

カテゴリー:通信

公開中のアプリ、是非ダウンロードしてみてください

2chまとめのたね

RSSを利用してさまざまなブログの情報をキュレーションしてくれるアプリ

インストールする

ひらがな戦記

OPENGL ES2 を利用したカルタのソーシャルゲーム

インストールする