Android Retful Web服务教程
在本教程中,我们将与Android集成到RESTFUL Web服务,将JSON返回为响应。
所以我们将从RESTful Web服务中获取JSON,然后将JSON响应呈现给Android自定义ListView。
例子 :
我已经实现了Restful WebServices JSON示例。
我将使用相同的例子来实现RESTful Web服务。
如果我们要部署以上Web服务,请使用以下URL来获取JSON数据
http://192.168.2.22:8080/JAXRSJsonExample/rest/countries
192.168.2.22是我机器的IP地址。
在计算机上实现此Web服务后,我们应该用IP地址替换它。
如果我们不想自己实现REST Web服务并希望低于JSON响应。
我们可以使用以下链接。
https://cdn.rawgit.com/arpitmandliya/androidrestjsonexample/master/countries.json我们将从上面的URL上获得以下JSON响应:
[ { "id":1, "countryName":"San Franceco" }, { "id":4, "countryName":"China" }, { "id":3, "countryName":"Nepal" }, { "id":2, "countryName":"Bhutan" } ]
我们从REST Web服务中获得了JSON数组。
如果我们不熟悉JSON,则可以通过JSON教程进行。
我们将渲染以上JSON响应Android自定义列表查看:
第1步:创建项目
创建一个Android应用程序ProjectNamed"AndroidRestjsonexample"。
第2步:创建布局
更改RES - >布局 - > Activity_main.xml如下所示:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="10dp" tools:context="com.theitroad.androidrestjsonexample.MainActivity"> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Fetching countries data" android:id="@+id/btnSubmit" <ListView android:id="@+id/android:list" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/btnSubmit" </RelativeLayout>
我们有一个按钮和ListView。
单击按钮时,我们将通过调用RESTful Web服务并在ListView上渲染它来填充ListView中的数据。
第3步:为行创建布局
正如我们在Activity_main.xml中声明listview小部件。
现在我们需要为单个行提供布局。
- 转到res - >布局
- 右键单击布局
- 单击"新建 - >文件"。
- 创建名为"row_item.xml"的文件,并在row_item.xml中粘贴以下代码。
<?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_columnWeight="1" android:layout_marginLeft="10dp" android:textSize="30dp" android:textColor="#1E90FF" android:id="@+id/textViewId" android:layout_row="0" android:layout_column="1" <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_columnWeight="1" android:layout_marginLeft="10dp" android:textSize="20dp" android:textColor="#4B0082" android:id="@+id/textViewCountry" android:layout_row="1" android:layout_column="1" </GridLayout>
第4步:创建模型对象国家/地区:
如果我们注意到,我们从RESTful Web服务中获取JSON数组,其中有4项。
每个项目都有两个属性ID和CountryName。
我们将为每个项目创建国家对象。
package com.theitroad.androidrestjsonexample; public class Country{ int id; String countryName; public Country(int i, String countryName) { super(); this.id = i; this.countryName = countryName; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getCountryName() { return countryName; } public void setCountryName(String countryName) { this.countryName = countryName; } }
步骤5:为ListView创建BaseAdapter
在创建捕获期之前,我们需要为自定义ListView行创建CustomCountrylist类。
package com.theitroad.androidrestjsonexample; import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.theitroad.androidrestjsonexample.Country; import com.theitroad.androidrestjsonexample.R; import java.util.ArrayList; public class CustomCountryList extends BaseAdapter { private Activity context; ArrayList countries; public CustomCountryList(Activity context, ArrayList countries) { // super(context, R.layout.row_item, countries); this.context = context; this.countries=countries; } public static class ViewHolder { TextView textViewId; TextView textViewCountry; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row=convertView; LayoutInflater inflater = context.getLayoutInflater(); ViewHolder vh; if(convertView==null) { vh=new ViewHolder(); row = inflater.inflate(R.layout.row_item, null, true); vh.textViewId = (TextView) row.findViewById(R.id.textViewId); vh.textViewCountry = (TextView) row.findViewById(R.id.textViewCountry); //store the holder with the view. row.setTag(vh); } else { vh = (ViewHolder) convertView.getTag(); } vh.textViewCountry.setText(countries.get(position).getCountryName()); vh.textViewId.setText(""+countries.get(position).getId()); return row; } public long getItemId(int position) { return position; } public Object getItem(int position) { return position; } public int getCount() { if(countries.size()<=0) return 1; return countries.size(); } }
此类用于填充ListView的数据。
GetView方法被调用以绘制每一行。
第6步:创建MainActivity
我们将创建一个添加AsyncTask的加法内部类GetServerData。
此类将在后台线程中进行HTTPS调用。
以下是使用ASYNCTASK时可能需要实现的三种方法。
- onpreexecute():在制作HTTP调用之前将在调用此方法。我们正在这里初始化ProgressDialog。
- DoInbackground:我们将在此方法中进行HTTP调用。我们使用HttpClConnection类进行HTTP调用。在执行此方法时,我们无法访问任何UI元素
- onPostexecute:执行Doinbackground方法后执行。在此方法中,我们将创建CustomCountryList对象并填充ListView数据。
更改src/main/packageName/mainActivity.java如下:
package com.theitroad.androidrestjsonexample; import android.app.Activity; import android.app.ProgressDialog; import android.os.AsyncTask; import android.os.Bundle; import android.os.StrictMode; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.Button; import android.widget.ListView; import android.widget.Toast; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import javax.net.ssl.HttpsURLConnection; import static android.content.ContentValues.TAG; public class MainActivity extends AppCompatActivity { private Button btnSubmit; String responseText; StringBuffer response; URL url; Activity activity; ArrayList countries=new ArrayList(); private ProgressDialog progressDialog; ListView listView; //In case if you deploy rest web service, then use below link and replace below ip address with yours //http://192.168.2.22:8080/JAXRSJsonExample/rest/countries //Direct Web services URL private String path = "https://cdn.rawgit.com/arpitmandliya/AndroidRestJSONExample/master/countries.json"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); activity = this; btnSubmit = (Button) findViewById(R.id.btnSubmit); listView = (ListView) findViewById(android.R.id.list); btnSubmit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { countries.clear(); //Call WebService new GetServerData().execute(); } }); } class GetServerData extends AsyncTask { @Override protected void onPreExecute() { super.onPreExecute(); //Showing progress dialog progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setMessage("Fetching conntry data"); progressDialog.setCancelable(false); progressDialog.show(); } @Override protected Object doInBackground(Object[] objects) { return getWebServiceResponseData(); } @Override protected void onPostExecute(Object o) { super.onPostExecute(o); //Dismiss the progress dialog if (progressDialog.isShowing()) progressDialog.dismiss(); //For populating list data CustomCountryList customCountryList = new CustomCountryList(activity, countries); listView.setAdapter(customCountryList); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { Toast.makeText(getApplicationContext(),"You Selected "+countries.get(position).getCountryName()+ " as Country",Toast.LENGTH_SHORT).show(); } }); } } protected Void getWebServiceResponseData() { try { url = new URL(path); Log.d(TAG, "ServerData: " + path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(15000); conn.setConnectTimeout(15000); conn.setRequestMethod("GET"); int responseCode = conn.getResponseCode(); Log.d(TAG, "Response code: " + responseCode); if (responseCode == HttpsURLConnection.HTTP_OK) { //Reading response from input Stream BufferedReader in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String output; response = new StringBuffer(); while ((output = in.readLine()) != null) { response.append(output); } in.close(); }} catch(Exception e){ e.printStackTrace(); } responseText = response.toString(); //Call ServerData() method to call webservice and store result in response // response = service.ServerData(path, postDataParams); Log.d(TAG, "data:" + responseText); try { JSONArray jsonarray = new JSONArray(responseText); for (int i = 0; i < jsonarray.length(); i++) { JSONObject jsonobject = jsonarray.getJSONObject(i); int id = jsonobject.getInt("id"); String country = jsonobject.getString("countryName"); Log.d(TAG, "id:" + id); Log.d(TAG, "country:" + country); Country countryObj=new Country(id,country); countries.add(countryObj); } } catch (JSONException e) { e.printStackTrace(); } return null; } }
第7步:在androidmanifest.xml中添加Internet权限
复制以下代码:
<uses-permission android:name="android.permission.INTERNET"
把它放在androidmanifest.xml中
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.theitroad.androidrestjsonexample"> <uses-permission android:name="android.permission.INTERNET" <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" <category android:name="android.intent.category.LAUNCHER" </intent-filter> </activity> </application> </manifest>
完成了,我们为Androidmanifest.xml添加了Internet权限。
您的应用程序现在应该能够联网了。