1. 程式人生 > >Android通過JSON資料格式和java服務後臺進行資料互動

Android通過JSON資料格式和java服務後臺進行資料互動

Android和JAVA後臺實現資料通訊

前言

進行綜合設計的時候,要求做個javaweb專案並掛到伺服器上,與此同時在Android上通過訪問後臺介面實現部分功能。經過了一番的摸索和踩坑,終於實現了和後臺服務的通訊登陸註冊和資訊列表顯示功能。這是 github 地址,先看一下效果。 在這裡插入圖片描述

專案介紹

目錄結構介紹

picture

功能介紹

登陸功能

首先在layout目錄下新建xml檔案進行佈局和定義樣式,然後註冊事件進行監聽,通過intent物件控制activity的跳轉,MainActivity類

public class MainActivity extends Activity implements OnClickListener{
//宣告全域性控制元件
	private EditText mPhoneNumberEditText;
    private EditText mPassWordEditText;
    private Button mLoginButton, mRegisterButton;
    private RadioButton admin, user;
    private String originAddress = "http://47.97.193.151/parkingsystem2/Login"; //登陸請求的網址介面
    
    Handler mHandler = new Handler(){  
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String result = "";

            if ("OK".equals(msg.obj.toString())){
                result = "success";
            }else if ("Wrong".equals(msg.obj.toString())){
                result = "fail";
            }else {
            	String data = msg.obj.toString();
//            	Toast.makeText(MainActivity.this, data, Toast.LENGTH_LONG).show();
            	try {
					JSONObject jsonObject = new JSONObject(data);
					String code = jsonObject.getString("code");
					if (code.equals("1")) {
						result = jsonObject.getString("data");
						
						//通過Bundle封裝資料在intent物件中,傳遞到不同的activity
						Bundle bundle = new Bundle();
						bundle.putString("data", result);
						//通過Intent控制Activity跳轉
						Intent intent = new Intent();
						intent.setClass(MainActivity.this, ListActivity.class);
						intent.putExtras(bundle);
						finish();
						startActivity(intent);
					}else {
						result = jsonObject.getString("data");
						Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
					}
				} catch (JSONException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }
            
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
        initEvent();
    }
    //初始化控制元件方法
    private void initView() {
        mPhoneNumberEditText = (EditText) findViewById(R.id.phoneNumberEditText);
        mPassWordEditText = (EditText) findViewById(R.id.passwordEditText);
        mLoginButton = (Button) findViewById(R.id.loginButton);
        mRegisterButton = (Button) findViewById(R.id.registerButton);
        admin = (RadioButton)findViewById(R.id.admin);
        user = (RadioButton)findViewById(R.id.user);
    }
    //註冊事件方法
    private void initEvent() {
        mLoginButton.setOnClickListener(this);
        mRegisterButton.setOnClickListener(this);
    }
    
    private boolean isInputValid() {
        //檢查使用者輸入的合法性,這裡暫且預設使用者輸入合法
        return true;
    }
    //實現介面onCreate方法
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.loginButton:{
                login();				//呼叫登陸方法
                break;
            }
            case R.id.registerButton: {
            	register();				//呼叫註冊方法
            	break;
            }
        }
    }
    //跳轉到註冊介面
    public void register() {
		Intent intent = new Intent();
		intent.setClass(MainActivity.this, RegisterActivity.class);  //跳轉
		startActivity(intent);  //啟動
		finish();
	}
    //登陸
    public void login() {
        //取得使用者輸入的賬號和密碼
        if (!isInputValid()){
            return;
        }
        String number = mPhoneNumberEditText.getText().toString().trim();
        String password = mPassWordEditText.getText().toString().trim();
        if (number.isEmpty()) {
        	Toast.makeText(MainActivity.this, "賬號不能為空!", Toast.LENGTH_LONG).show();
        	return;
		}else if (password.isEmpty()) {
			Toast.makeText(MainActivity.this, "密碼不能為空!", Toast.LENGTH_LONG).show();
			return;
		}else if (!admin.isChecked() && !user.isChecked()) {
			Toast.makeText(MainActivity.this, "請選擇許可權!", Toast.LENGTH_LONG).show();
			return;
		}
        HashMap<String, String> params = new HashMap<String, String>();
        params.put(User.USERNAME, number);
        params.put(User.PASSWORD, password);
        if (admin.isChecked()) {
        	params.put(User.POWER, "1");
		}else if (user.isChecked()) {
			params.put(User.POWER, "2");
		}
        
        try {
        //發起HTTP請求
            String compeletedURL = HttpUtil.getURLWithParams(originAddress, params); //originAddress請求地址, params請求引數
            HttpUtil.sendHttpRequest(compeletedURL, new HttpCallbackListener() {
                @Override
                public void onFinish(String response) {		//請求回撥函式,response是響應的資料
                    Message message = new Message();
                    message.obj = response;
                    mHandler.sendMessage(message);    //給Handlder傳遞資料
                }

                @Override
                public void onError(Exception e) {
                    Message message = new Message();
                    message.obj = e.toString();
                    mHandler.sendMessage(message);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

特別重要

在進行Activity跳轉時,需要在 AndroidMainfest.xml 配置檔案註冊,同時網路請求也要配置允許設定。 picture

網路請求封裝類

public class HttpUtil {
    //封裝的傳送請求函式
    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
        if (!HttpUtil.isNetworkAvailable()){
            //這裡寫相應的網路設定處理
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                try{
                    URL url = new URL(address);
                    //使用HttpURLConnection
                    connection = (HttpURLConnection) url.openConnection();
                    //設定方法和引數
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    connection.setDoInput(true);
                    connection.setDoOutput(true);
                    //獲取返回結果
                    InputStream inputStream = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null){
                        response.append(line);
                    }
                    //成功則回撥onFinish
                    if (listener != null){
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    //出現異常則回撥onError
                    if (listener != null){
                        listener.onError(e);
                    }
                }finally {
                    if (connection != null){
                        connection.disconnect();
                    }
                }
            }
        }).start();
    }
    //組裝出帶引數的完整URL
    public static String getURLWithParams(String address,HashMap<String,String> params) throws UnsupportedEncodingException {
        //設定編碼
        final String encode = "UTF-8";
        StringBuilder url = new StringBuilder(address);
        url.append("?");
        //將map中的key,value構造進入URL中
        for(Map.Entry<String, String> entry:params.entrySet())
        {
            url.append(entry.getKey()).append("=");
            url.append(URLEncoder.encode(entry.getValue(), encode));
            url.append("&");
        }
        //刪掉最後一個&
        url.deleteCharAt(url.length() - 1);
        return url.toString();
    }
    //判斷當前網路是否可用
    public static boolean isNetworkAvailable(){
        return true;
    }
}


回撥監聽介面類
public interface HttpCallbackListener {
	void onFinish(String response);

    void onError(Exception e);
}

註冊功能

註冊功能和登陸功能基本流程相同,只不過增加了兩個控制元件,請求的介面一樣,不過請求的引數不一樣,具體流程可以參考下 github 的原始碼

列表顯示功能

登陸成功後,後臺服務響應返回一個 json 資料格式的資料,需要解析 json 格式資料並顯示在列表上

{"code":1,
"data":[
{"cardtype":"VIP","cartype":"小型車","id":1,"number":"111","sum":"¥1011","time":"每小時"},
{"cardtype":"VIP","cartype":"中型車","id":2,"number":"112","sum":"¥12","time":"每小時"},
{"cardtype":"VIP","cartype":"大型車","id":3,"number":"113","sum":"¥15","time":"每小時"},
{"cardtype":"普通卡","cartype":"小型車","id":4,"number":"114","sum":"¥15","time":"每小時"},
{"cardtype":"普通卡","cartype":"中型車","id":5,"number":"115","sum":"¥20","time":"每小時"},
{"cardtype":"普通卡","cartype":"大型車","id":6,"number":"116","sum":"¥25","time":"每小時"}
]}

藉助 JSONArrayJSONObject 兩個物件將 json 資料 通過雜湊值hash存放在 ArrayList 物件上,然後通過 simpleAdapter 介面卡將 hash 的鍵list_item_activity.xml檔案 的控制元件 id 項對應顯示列表

public class ListActivity extends Activity {
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		ListView listView;  //宣告一個ListView物件
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		//獲取intent物件上的傳過來的資料
		Bundle myBundle = this.getIntent().getExtras();
		String data = myBundle.getString("data");
		setContentView(R.layout.list_activity);
		//存放json資料
		List<HashMap<String, String>> list = new ArrayList<HashMap<String,String>>();
		
		try {
			JSONArray jsonArray = new JSONArray(data);
			for (int i = 0; i < jsonArray.length(); i++) {
				JSONObject jsonObject = (JSONObject)jsonArray.get(i);
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("id",jsonObject.getString("id"));
				map.put("enterPort",jsonObject.getString("cardtype"));
				map.put("exitPort",jsonObject.getString("cartype"));
				map.put("parkName",jsonObject.getString("number"));
				map.put("parkTel",jsonObject.getString("sum"));
				map.put("parkTotal",jsonObject.getString("time"));
				list.add(map);
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		String[] str = new String[]{"id", "enterPort", "exitPort", "parkName", "parkTel", "parkTotal"}; //陣列存放對應上面hash的鍵
		int[] rId = new int[]{R.id.park_id, R.id.enter, R.id.exit, R.id.parkname, R.id.phone, R.id.total}; //對應list_item.activity.xml檔案的控制元件id
		SimpleAdapter simpleAdapter = new SimpleAdapter(ListActivity.this, list, R.layout.list_item_activity, str, rId); //引數,第一個是列表Activity的類,第二個引數是ArrayList資料,第三個引數是list_item_activity的layout的id,第四和第五對應上面的兩個資料,分別為hash鍵陣列和控制元件id陣列
		listView = (ListView)this.findViewById(R.id.listview);
		listView.setAdapter(simpleAdapter);
	}
}