الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيفية الحصول على البيانات عن طريق الـ JSON فى الاندرويد

بدأه Mahmoud Kelany في 11 أكتوبر 2012 · 1 رد · 7,565 مشاهدة · في Android
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمه الله وبركاته

ان شاء الله سوف اقوم بشرح كيفيه التعامل مع البيانات التى على شكل JSON

وهى شكل متفق عليه مثل الـ XML ولكنه يختلف قليلا ويستخدم لنقل البيانات

وهو ما يتعامل به الفيس بوك والتويتر (وهو مثالنا اليوم)

مثال على التويتر

https://api.twitter.com/1/statuses/user_timeline.json?screen_name=jkelanycompany

مثال على الفيس بوك

https://graph.facebook.com/jkelanydeveloper

هذا هو شكل الـ JSON data

post-217802-009265600 1349920400_thumb.p

عباره عن Array او Object او الدمج بينها

والصوره توضح ايهما array وهو عباره ان اقواس مربعه [ ]

والـ object وهو عبارة عن اقواس عادية { }

كالعادة نحب ان نكون منظمين فقومت بعمل UserTweets bean

package com.jkelany.json;

public class UserTweets {
	private String text;
	private String date;
	private String userName;
	private String screenName;

	public UserTweets() {
	}

	public UserTweets(String text, String date, String userName,
			String screenName) {
		super();
		this.text = text;
		this.date = date;
		this.userName = userName;
		this.screenName = screenName;
	}

	public String getText() {
		return text;
	}

	public void setText(String text) {
		this.text = text;
	}

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public String getScreenName() {
		return screenName;
	}

	public void setScreenName(String screenName) {
		this.screenName = screenName;
	}

	@Override
	public String toString() {
		return screenName + "(" + userName + ") @ " + date + "\n" + text + "\n";
	}

}

حتى نتمكن من التعامل مع البيانات بشكل منظم wacko.gif

قومت بتعريف متغيرين احدهما لاسم المستخدم والاخر لرابط الموقع والمثال لدينا على التوتير

private String username = "jkelanycompany";
private final String TWITTER_API_URL = "https://api.twitter.com/1/statuses/user_timeline.json?";

لكى نحصل على البيانات عن طريق الـ JSON قومنا ببناء داله تقوم بذلك

public JSONArray getUserTwittes(String username)
			throws ClientProtocolException, IOException, JSONException {
		StringBuilder sb = new StringBuilder(TWITTER_API_URL);
		sb.append("screen_name=");
		sb.append(username);

		HttpGet httpGet = new HttpGet(sb.toString());
		HttpResponse httpResponse = httpClient.execute(httpGet);
		int status = httpResponse.getStatusLine().getStatusCode();
		if (status == 200) {
			HttpEntity httpEntity = httpResponse.getEntity();
			String jsonData = EntityUtils.toString(httpEntity);
			return new JSONArray(jsonData);
		}
		return null;
	}

سوف نشرحها حالا

فقد قومنا باضافه الكلمة screen_name= على الـ URL وبعدها اسم المستخدم ليكون الشكل النهائى للرابط كما ذكرنا من قبل

StringBuilder sb = new StringBuilder(TWITTER_API_URL);
		sb.append("screen_name=");
		sb.append(username);

اقتباس

لكن بناء داله ووضعها بهذا الشكل لكى نتمكن بعد ذلك بارسال فقط اى اسم مستخدم لهذه الداله نقوم بجلب التدوينات الخاصه بيه ع التويتر

بعدها نقوم بانشاء كائن من الـ HttpGet ونقوم بارسال العنوان كاملا لها لكى تجلب البيانات من هذا العنوان

HttpGet httpGet = new HttpGet(sb.toString());

ثم نقوم بانشاء كائن من الـHttpClient لكى نتعامل مع البرتوكول HTTP وننفذ جلب البيانات عن طريق استدعاء الداله execute على هذا الكائن

وتعود لنا بالـHttpResponse

HttpClient httpClient = new DefaultHttpClient();
HttpResponse httpResponse = httpClient.execute(httpGet);

من الـ HttpResponse نحصل على كود الحاله هل هو مساوى لـ 200 وهو يعنى ان العمليه تمت بنجاح

اذا كانت 200 فمعنى ذلك ان الـ HttpResponse تحتوى على البيانات من الرابط

ويمكن الحصول عليها باستدعاء الداله getEntity على الـhttpResponse

وهى ما تعود لنا بكائن من الـHttpEntity

ومن ثم نريد تحويل هذا الكائن من النوع HttpEntity الى String

نستخدم الداله EntityUtils.toString لعمل ذلك

وبعد ذلك نقوم بارسال قيمه الـ String لانشاء بها JSONArray

وهكذا حصلنا على JSONArray الخاصه بالرد من الموقع

HttpResponse httpResponse = httpClient.execute(httpGet);
		int status = httpResponse.getStatusLine().getStatusCode();
		if (status == 200) {
			HttpEntity httpEntity = httpResponse.getEntity();
			String jsonData = EntityUtils.toString(httpEntity);
			return new JSONArray(jsonData);
		}

لكى نحصل على تنفيذ الداله السابقه لابد من استخدام فئة ترث من الـ AsyncTask وهى اللى تجعل التطبيق يقوم بعمل اشياء فى الـBackground

وبعد ان يفرغ يقوم بتنفيذ حدث معين او عرض البيانات فى الشاشه

لماذا سوف نستخدم ذلك لان الحصول على البيانات من الموقع يستغرق وقت فى ذلك

لذلك قومنا ببناء الفئة ReadJSONTwitterData والتى ترث من الفئة AsyncTask

ليكون بالشكل التالى

class ReadJSONTwitterData extends AsyncTask<String, Integer, UserTweets[]> {

@Override
		protected UserTweets[] doInBackground(String... params) {
}

@Override
		protected void onPostExecute(UserTweets[] twittes) {
}


}

لكن ماذا عن String , Integer , UserTweets[]

اول مدخل String وهو يحدد نوع المدخلات للداله doInBackground

ثانى مدخل Integer وهو يحدد قيمه الـ progress وقد تستخدم فى عمل شكل ProgressBar وتحديث القيمه بداخله بهذه القيمه

ثالث مدخل وهو ما يحدد نتيجه الداله doInBackground ومدخلات الداله onPostExecute

ماذا عن الداله doInBackground

هى من تقوم بفعل الاتصال والحصول على البيانات فى خلفيه البرنامج

ماذا عن الداله onPostExecute

هى ما تستدعى عندما تفرغ الداله doInBackground من الحصول على البيانات او فعل الاوامر

ولاستدعاء هذه الفئة نقوم

new ReadJSONTwitterData().execute(KEYS);

ونعطى الداله execute جميع المدخلات التى نريدها وهى هنا عباره عن مصفوفه من النوع String

private String[] KEYS = new String[] { "text", "created_at", "user","screen_name", "name" };

حيث ان text هو يمثل مفتاح للحصول على نص التدوينه

created_at وهو ايضا مفتاح للحصول على تاريخ التدوينه

user وهى مفتاح ولكنه يمثل كائن كامل من البيانات

screen_name وهو مفتاح يعبر عن اسم المستخدم على التويتر

name وهو عباره عن مفتاح يمثل الاسم الكامل للشخص على التويتر

post-217802-094684400 1349920423_thumb.p

@Override
		protected UserTweets[] doInBackground(String... params) {
			try {
				JSONArray jsonArr = getUserTwittes(username);
				if (jsonArr != null) {
					UserTweets uts[] = new UserTweets[jsonArr.length()];
					for (int i = 0; i < uts.length; i++) {
						JSONObject ob = jsonArr.getJSONObject(i);
						String text = ob.getString(params[0]);
						String date = ob.getString(params[1]);

						ob = jsonArr.getJSONObject(i).getJSONObject(params[2]);
						String username = ob.getString(params[3]);
						String name = ob.getString(params[4]);

						date = new SimpleDateFormat("EEE, MMMM dd, yyyy hh:mm:ss a")
								.format(Date.parse(date));
						UserTweets ut = new UserTweets(text, date, username,
								name);
						uts = ut;
					}
					return uts;
				} else {
					return null;
				}
			} catch (Exception e) {
				e.printStackTrace();
		 				}
			return null;
		}

نقوم باستدعاء الدالة getUserTwittes داخل الـdoInBackground

وبعدها تعود لنا الـJSONArray

نقوم تفحص هل تحتوى على بيانات ام هى null

ومن ثم نقوم بعمل مصفوفه على حسب عدد التدوينات وهى طول الJSONArray

UserTweets uts[] = new UserTweets[jsonArr.length()];

ونقوم بعمل لووب على عدد التدوينات

JSONObject ob = jsonArr.getJSONObject(i);
String text = ob.getString(params[0]);
String date = ob.getString(params[1]);

نقوم باخد الـgetJSONObject من المصفوفه الخاصه بالـ jsonArr

وبم انها مصفوفه اساسية نقوم باخد قيمه الـ text , created_at بكل سهولة

لكن بالنسبه الخاصه بالمستخدم فى بيانات داخل كائن user فلذلك لا يمكن الحصول عليها بسهوله كما حصلت على نص وتاريخ التدوينه

سوف نقوم بالدخول على الكائن user الاول وبعدها نقوم بالحصول على البيانات الخاصه به مثل الـ name , screen_name

ob = jsonArr.getJSONObject(i).getJSONObject(params[2]);
String username = ob.getString(params[3]);
String name = ob.getString(params[4]);

وبعدها نقوم بعمل كائن جديد من الـ UserTweets ووضعه فى مصفوفة الـ uts

بعد ان تقوم هذه الداله بانهاء العمل يتم استدعاء الداله onPostExecute وهى ما تاخد فى مدخلاتها مصفوفه من الـ UserTweets

يتم ارساله مباشره فور الانتهاء من العمل بالداله doInBackground

وهى التى تقوم بفحص البيانات داخل المصفوفه هل تحتوى على بيانات ام null

ومن ثم تعرض رساله خطأ او ترسل البيانات لداله تقوم ببناء البيانات داخل الـ ListView

فهى هذه المره سوف نقوم ببناء الـ Custom Adapter الخاص بالـ listView

لاننا نريد ان تظهر بشكل افضل

لذلك سوف نستخدم الـ SimpleAdapter لعمل ذلك

وهو ما ياخد الـ Context وبعدها list ولكنها عباره عن Hashmap من القيم التى سوف يعمل بينها تواصل لوضعها فى مكانها الصحيح

وبعدها شكل العنصر فى الـ listview هو عباره عن شكل XML تم بناءه عباره عن 3 TextView بشكل جمالى

وبعد ذلك مصفوفه من الـ String تحتوى على الـمفاتيح المستخدمة فى الـ Hashmap

وبعدها مصفوفه من الـ int تحتوى على ids الخاصه بالمكونات الموجود فى الـ View

وهذه هى الداله التى تقوم بذلك

private void setDataToList(UserTweets tweets[]) {
		List<HashMap<String, String>> maps = new ArrayList<HashMap<String, String>>();
		for (int i = 0; i < tweets.length; i++) {
			HashMap<String, String> hm = new HashMap<String, String>();
			hm.put(KEYS[0], tweets.getText());
			hm.put(KEYS[1], tweets.getDate() +	 "\n");
			hm.put(KEYS[2],
					tweets.getScreenName() + "(" + tweets.getUserName()
							+ ")");

			maps.add(hm);
		}

		simpleAdapter = new SimpleAdapter(this, maps, R.layout.item_tweet_list,
				new String[] { KEYS[0], KEYS[1], KEYS[2] }, new int[] {
						R.id.tv_tweet_text, R.id.tv_tweet_date,
						R.id.tv_user_info });

		tweetsListView.setAdapter(simpleAdapter);
	}

وهذا هو الكود كاملا

package com.jkelany.json;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
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.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class JSONTwitterActivity extends Activity {
	private String username = "jkelanycompany";
	private final String TWITTER_API_URL = "https://api.twitter.com/1/statuses/user_timeline.json?";

	private ListView tweetsListView;
	private TextView twittesTextView;
	private HttpClient httpClient;
	private SimpleAdapter simpleAdapter;
	private String[] KEYS = new String[] { "text", "created_at", "user",
			"screen_name", "name" };
	private ProgressDialog progressDialog;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		twittesTextView = (TextView) findViewById(R.id.tv_no_tweets);
		tweetsListView = (ListView) findViewById(R.id.lv_tweets);
		showLoadingDialog();
		httpClient = new DefaultHttpClient();

		new ReadJSONTwitterData().execute(KEYS);
	}

	private void showLoadingDialog() {
		progressDialog = new ProgressDialog(this);
		progressDialog.setCancelable(false);
		progressDialog.setMessage("Loading '" + username + "' tweets...");
		progressDialog.show();
	}

	public JSONArray getUserTwittes(String username)
			throws ClientProtocolException, IOException, JSONException {
		StringBuilder sb = new StringBuilder(TWITTER_API_URL);
		sb.append("screen_name=");
		sb.append(username);

		HttpGet httpGet = new HttpGet(sb.toString());
		HttpResponse httpResponse = httpClient.execute(httpGet);
		int status = httpResponse.getStatusLine().getStatusCode();
		if (status == 200) {
			HttpEntity httpEntity = httpResponse.getEntity();
			String jsonData = EntityUtils.toString(httpEntity);
			return new JSONArray(jsonData);
		}
		return null;
	}

	class ReadJSONTwitterData extends AsyncTask<String, Integer, UserTweets[]> {

		@Override
		protected UserTweets[] doInBackground(String... params) {
			try {
				JSONArray jsonArr = getUserTwittes(username);
				if (jsonArr != null) {
					UserTweets uts[] = new UserTweets[jsonArr.length()];
					for (int i = 0; i < uts.length; i++) {
						JSONObject ob = jsonArr.getJSONObject(i);
						String text = ob.getString(params[0]);
						String date = ob.getString(params[1]);

						ob = jsonArr.getJSONObject(i).getJSONObject(params[2]);
						String username = ob.getString(params[3]);
						String name = ob.getString(params[4]);

						date = new SimpleDateFormat("EEE, MMMM dd, yyyy hh:mm:ss a")
								.format(Date.parse(date));
						UserTweets ut = new UserTweets(text, date, username,
								name);
						uts = ut;
					}
					return uts;
				} else {
					return null;
				}
			} catch (Exception e) {
				e.printStackTrace();
				twittesTextView.setText(e.getMessage());
				twittesTextView.setVisibility(View.VISIBLE);
				progressDialog.dismiss();
			}
			return null;
		}

		@Override
		protected void onPostExecute(UserTweets[] twittes) {
			if (twittes == null) {
				twittesTextView.setVisibility(View.VISIBLE);
				twittesTextView
						.setText("'"
								+ username
								+ "' may be not have tweets\nor may be not a twitter user.");
				progressDialog.dismiss();
			} else {
				setDataToList(twittes);
			}
		}
	}

	private void setDataToList(UserTweets tweets[]) {
		List<HashMap<String, String>> maps = new ArrayList<HashMap<String, String>>();
		for (int i = 0; i < tweets.length; i++) {
			HashMap<String, String> hm = new HashMap<String, String>();
			hm.put(KEYS[0], tweets.getText());
			hm.put(KEYS[1], tweets.getDate() + "\n");
			hm.put(KEYS[2],
					tweets.getScreenName() + "(" + tweets.getUserName()
							+ ")");

			maps.add(hm);
		}

		simpleAdapter = new SimpleAdapter(this, maps, R.layout.item_tweet_list,
				new String[] { KEYS[0], KEYS[1], KEYS[2] }, new int[] {
						R.id.tv_tweet_text, R.id.tv_tweet_date,
						R.id.tv_user_info });

		tweetsListView.setAdapter(simpleAdapter);
		progressDialog.dismiss();
	}
}

صور من عمل التطبيق

post-217802-030568400 1349920477_thumb.p

post-217802-002158000 1349920480_thumb.p

post-217802-050900900 1349920485_thumb.p

لتحميل الكود

TestJSONwithTwitter.zip

بالتوفيق ان شاء الله

المرفقات
json.pngtwitter_keys.pngdevice-2012-10-11-022201.pngdevice-2012-10-11-022251.pngdevice-2012-10-11-022818.png

Software Developer
Mahmoudkelany.com


 

#2

مشكور أخي ...


انصح  بإستخدام lib متطور :لحفظ النظام  : marshalling وهو GSON .... وهو سهل الإستخدام وفعال في حالات Json complex ....حين نريد إعادة تكوين Object به مجموعات من مثلاً HASHMAP و-ARRAYLIST .....


شكراً 

لا إله إلا الله محمد رسول الله  

Blog

GitHub

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…