搜尋此網誌

2015年8月20日 星期四

【Android】實作從html讀取JSON 〈2〉

最近想測試從網頁上讀Json並在Android手機上

舊方法:【Java】實作從html讀取JSON (應該是說在Android API 22之後Apache HTTP Client Removal,Http Get /post的方法被捨棄 )

新方法:以HttpURLConnection實作讀取

因為是要顯示在Android 手機上,那種耗時的網路連線、資料整理的動作並不能在main thread中做處理,所以需要額外開一條Thread在background做處理或是以AsyncTask。
在這裡使用AsyncTask來處理相關動作。(更多關於AsyncTask)

較重要的程式碼,如下:

AndroidManifest.xml
須加上
<uses-permission android:name="android.permission.INTERNET" />
允許使用網路
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE">
</uses-permission>
允許檢查網路狀態

FetchTask.java
public class FetchTask extends AsyncTask<String,Void,String> {

    interface OnFetchListener {
        public void OnAirDataFetchFinished();
    }

    private OnFetchListener onFetchListener;

    public void setOnFetchListener(OnFetchListener listener) {
        onFetchListener =listener;
    }



    @Override
    protected String doInBackground(String... params) {
        DataFetcher.getInstance().fetchAirData();
        return  DataFetcher.getInstance().getResult();
    }

    @Override
    protected void onPostExecute(String s) {
        onFetchListener.OnAirDataFetchFinished();
    }
}
DataFetcher.java
public class DataFetcher {
    private StringBuilder airData = new StringBuilder();
    private String path = "http://......";
    private ArrayList<AirSiteObject> mItems;

    private DataFetcher() {

    }

    private static DataFetcher mFetcher;

    public static DataFetcher getInstance() {
        if (null == mFetcher) {
            mFetcher = new DataFetcher();
        }
        return mFetcher;
    }

    public void fetchAirData() {
        HttpURLConnection httpURLConnection = null;
        try {
            URL url = new URL(path);
            httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.connect();
            int status = httpURLConnection.getResponseCode();
            switch (status) {
                case 200:
                case 201:
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8"));
                    String line;
                    while ((line = bufferedReader.readLine()) != null) {
                        airData.append(line + "\n");
                    }
                    bufferedReader.close();

            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            if (httpURLConnection != null) {
                httpURLConnection.disconnect();

            }
        }

    }

    public String getResult() {
        return airData.toString();
    }

    //JSONParser
    public ArrayList<AirSiteObject> GetAirData(String result) {
        mItems =new ArrayList<AirSiteObject>();
        JSONObject obj;
        try {
            JSONArray jsonArray = new JSONArray(result);
            for (int i = 0; i < jsonArray.length(); i++) {
                obj = jsonArray.getJSONObject(i);
                mItems.add(new AirSiteObject(obj));
            }

        } catch (JSONException e) {
            Log.e("MYAPP", "unexpected JSON exception", e);
        }
        return mItems;
    }
}
MainActivity.java
private FetchTask mFetchAirDataTask;
記得要
implements FetchTask.OnFetchListener
onCraete method
mFetchAirDataTask = new FetchTask();mFetchAirDataTask.setOnFetchListener(this);executeTask();

判斷網路是否正常
private void executeTask() {
    if (ToolsHelper.isNetworkAvailable(this)) {
        mFetchAirDataTask.execute();    } else {
        Toast.makeText(this, "未偵測到網路,請確認網路狀況。", Toast.LENGTH_LONG).show();    }
}

實作OnFetchListener介面的OnAirDataFetchFinished method
@Override
    public void OnAirDataFetchFinished() {
        String result = DataFetcher.getInstance().getResult();
        listView.setAdapter(new ViewItemAdapter(this, DataFetcher.getInstance().GetAirData(result)));
        if (DataFetcher.getInstance().GetAirData(result).size() == 0) {
            Toast.makeText(this, "資料讀取失敗,請稍候再重試。", Toast.LENGTH_LONG).show();
        }
    }

2015年8月14日 星期五

【Android】工具 - RoboGuice

感覺和奶油刀差不多的工具
RoboGuice  https://github.com/roboguice/roboguice/wiki

Example:
    class AndroidWay extends Activity { 
        TextView name; 
        ImageView thumbnail; 
        LocationManager loc; 
        Drawable icon; 
        String myName; 

        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            setContentView(R.layout.main);
            name      = (TextView) findViewById(R.id.name); 
            thumbnail = (ImageView) findViewById(R.id.thumbnail); 
            loc       = (LocationManager) getSystemService(Activity.LOCATION_SERVICE); 
            icon      = getResources().getDrawable(R.drawable.icon); 
            myName    = getString(R.string.app_name); 
            name.setText( "Hello, " + myName ); 
        } 
    } 

written using RoboGuice:
    @ContentView(R.layout.main)
    class RoboWay extends RoboActivity { 
        @InjectView(R.id.name)             TextView name; 
        @InjectView(R.id.thumbnail)        ImageView thumbnail; 
        @InjectResource(R.drawable.icon)   Drawable icon; 
        @InjectResource(R.string.app_name) String myName; 
        @Inject                            LocationManager loc; 

        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState); 
            name.setText( "Hello, " + myName ); 
        } 
    } 

【Android Studio】auto import all of the shortcut


心得:
從Eclipse轉到Android Studio實在太累了,一堆功能又不太一樣,一直卡在Debug要如在AS上操作比較順利,常常知道Eclipse的功能,但轉到AS不知道要去哪裡設定?再加上英文關鍵字也不知道要如何下?

比如說:
URL url = new URL();
使用eclipse時(Shift+Ctrl+O)會自動說明需要加上try ... catch ...exception 或 throws ...exception,並自動產生出來。
但在AS只會和你說 Unhandled exception: ...之類的,但是要如何解決,需要自己去查api要如何使用,沒有直接提示。

其實是有的,只是這個功能被關閉哩 (= =|||)

StackOverflower類似的問題:
Is there any way of auto importing (like in Eclipse Shift+Ctrl+O) in Android Studio?
I have found only Ctrl+Alt+O which ask for each thing, and I have to press Alt+Enter to accept it.
No way to do it faster?

For Windows/Linux, you can go to File -> Settings -> Editor -> General -> Auto Import -> Java and make the following changes:
  • change Insert imports on paste value to All
  • markAdd unambigious imports on the fly option as checked
On a Mac, do the same thing in Android Studio -> Preferences






【Android】工具 - Butterknife

http://jakewharton.github.io/butterknife/

1.Download the latest JAR or grab via Maven
2.Gradle
compile 'com.jakewharton:butterknife:7.0.1'

Example
class ExampleActivity extends Activity {
  @Bind(R.id.user) EditText username;
  @Bind(R.id.pass) EditText password;

  @BindString(R.string.login_error)
  String loginErrorMessage;

  @OnClick(R.id.submit) void submit() {
    // TODO call server...
  }

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
    // TODO Use fields...
  }
}
-----------------------------------------------
ButterKnife後,
讓Annotation單獨一行顯示,
不必再切成兩行,設定:
File > Settings > Editor > Code Style > Java > Filed annotations > Do not wrap after single annotation 打勾。

【Android Studio】 導入外部library 教學

ref:
http://chris0903.blogspot.tw/2013/07/android-studiolibrary.html

【Android】Fragment常用功能

ref:
http://btsken.blogspot.tw/2014/10/android-fragment.html

【Android】AsyncTask使用上的注意事項

ref:

  1. http://blog.30sparks.com/android-asynctask-problems/
  2. http://themakeinfo.com/2015/04/retrofit-android-tutorial/

doInBackground方法和onPostExecute的參數必須對應,這兩個參數在AsyncTask聲明的泛型參數列表中指定。
第一個為doInBackground接受的參數。
第二個為顯示進度的參數。
第三個為doInBackground返回和onPostExecute傳入的參數。

【Android Studio】ActionBarActivity is deprecated

ref:
http://developer.android.com/tools/support-library/index.html
http://android-developers.blogspot.tw/2015/04/android-support-library-221.html

Since the version 22.1.0, the class ActionBarActivity is deprecated. You should use AppCompatActivity.

解決方法:
https://www.youtube.com/watch?t=49&v=5Be2mJzP-Uw

需修改以下兩處:

  • AndroidManifest.xml
    • <application android:theme="@style/Theme.AppCompat">
  • MainActivity.xml
    • public class MainActivity extends AppCompatActivity

2015年8月7日 星期五