Android ile bir Web Sitesinden Veri Okuma (Php & JSON)
Merhabalar;Bu yazıda çoğu profesyonel uygulamalarda kullanılan web servis yardımıyıla internette herhangi bir siteden veri çekerek android yani client tarafında kullanmadan bahsedeceğim.Örneğin; bir haber uygulaması geliştiriyoruz.Fakat geliştirdiğimiz sitenin RSS i yetersiz yada yok ise mecburen sitenin kaynağına inerek html tag larini parse etmemiz gerekecek. İşte bu noktada aslında kullanabileceğimiz çeşitli yöntemler var. En çok kullanılanlar ise Client yani Android tarafında JSOUP kütüphanesi kullanarak,diğeri de php ile bot yazıp sonuçları web servis ile almak. Ben ikisini de ayrı yazı olarak anlatmayı düşündüm.Ama ben genelde bu tarz projelerde web servisi tercih ediyorum.Tag lari parçalama kısmını tamamen web serviste halledip android tarafında sadece web servisi çağırmak kalıyor. Veriyi çekeceğimiz site muhtemelen bizim elimizde olmadığı için site sahibi bir tane bile tag değiştirse android tarafını oturup baştan düzenlememiz gerekicek.Ama bunun yerine bu işlemi serviste yapmak daha kolay.Özellikle de php ile.
Şimdi bu yazıda yapacağımız örnek projeden bahsedeyim. Android kısmında sitemizdeki yazıları çekeceğiz.Tabi biraz php bilmek gerekiyor ama mantığı anlarsanız zorlanmazsınız.Çok karışık işler yapmayacağız. Siteden neleri çekeceğiz görsel olarak gösterelim:
Şimdi de çekeceğimz bu verilerin kaynaktaki kodlarını görelim.Hangi class da olduğu yada hangi id ye sahip vb. Sonrasında da web servisi yazmaya başlayacağız.
(Öğeyi denetle yaptığımızda gelen kodlar ile kaynaktaki kodlar farklı olabiliyor.Bot yazarken sonuç alamazsak kaynağı görüntüleyeceğiz.)
Şimdi web servisi yazmaya başlayalım.PHP ile bot yaparken aslında genelde 2 yol kullanılır. Birisi curl diğeri de file_get_gontents metodu. Curl daha fonksiyonel . O yüzden curl kullanarak hazırlayacağım botu.Ama ilerleyen derslerde file_get_contents ile de bir yazı yazmayı düşünüyorum.
Şimdi artık web servisimizi oluşturalım. thecodeprogram.php olarak oluşturdum ben. Gerekli açıklamaları kodlar üzerinde yaptım :
thecodeprogram.php
<?php
header('Content-Type: text/html; charset=utf-8');
$curl_handle=curl_init();
curl_setopt($curl_handle, CURLOPT_URL,'http://www.thekodprogram.com/'); //Sitemizin URL adresi
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'deneme');
$query = curl_exec($curl_handle); //Burada Curl çalışıyor ve linkteki bütün içerikler query değişkeninde tutuluyor.
curl_close($curl_handle);
//query değişkeninden almak istediğimiz kısmı bildiriyoruz.
//Burada (.*?) ile belirtilen yer değişecek kısım.Yani anasayfada bir sürü yazı başlığı mevcut.
//Bizde bunların değişebileceğini derleyiciye (.*?) ile bildirdik.
$parcala_baslik='@<h2 class="post-box-title"><a href="(.*?)">(.*?)</a></h2>@si';
//Burada da query içinden istediğimiz kısmı parçalayıp $basliklar değişkenine atıyoruz.
preg_match_all($parcala_baslik, $query, $basliklar);
echo "<pre>";
print_r($basliklar);
"</pre>";
?>
Şuan başlıkları aldık fakat daha bitmedi tabiki.Çıktısını göstermek için koydum.Devam edeceğiz fakat yukarıdaki kod bloğu bize şu çıktıyı verdi : Gördüğümüz gibi array şeklinde sonuçlar aldık.İşte biz bu arraylarin indekslerini json dizimize atıp döndüreceğiz. Mantık basit arkadaşlar.Şimdi web servise özet ve resim için eklemeler yapalım:
Özet eklemesi ile web servis devam :
<?php
header('Content-Type: text/html; charset=utf-8');
$curl_handle=curl_init();
curl_setopt($curl_handle, CURLOPT_URL,'http://www.thekodprogram.com/'); //Sitemizin URL adresi
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'deneme');
$query = curl_exec($curl_handle); //Burada Curl çalışıyor ve linkteki bütün içerikler query değişkeninde tutuluyor.
curl_close($curl_handle);
//query değişkeninden almak istediğimiz kısmı bildiriyoruz.
//Burada (.*?) ile belirtilen yer değişecek kısım.
//Yani anasayfada bir sürü yazı başlığı mevcut.Bizde bunların değişebileceğini derleyiciye (.*?) ile bildirdik.
$parcala_baslik='@<h2 class="post-box-title"><a href="(.*?)">(.*?)</a></h2>@si';
//Burada da query içinden istediğimiz kısmı parçalayıp $basliklar değişkenine atıyoruz.
preg_match_all($parcala_baslik, $query, $basliklar);
$parcala_ozet='@<p>(.*?)</p>@si'; //Özet için de query içinde arayacağımız kısımı bildirdik.
preg_match_all($parcala_ozet, $query, $ozetler);
print_r($ozetler);
?>
Şimdi son olarak da resimleri alalım.
<?php
header('Content-Type: text/html; charset=utf-8');
$curl_handle=curl_init();
curl_setopt($curl_handle, CURLOPT_URL,'http://www.thekodprogram.com/'); //Sitemizin URL adresi
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'deneme');
//Burada Curl çalışıyor ve linkteki bütün içerikler query değişkeninde tutuluyor.
$query = curl_exec($curl_handle);
curl_close($curl_handle);
//query değişkeninden almak istediğimiz kısmı bildiriyoruz.
//Burada (.*?) ile belirtilen yer değişecek kısım.
//Yani anasayfada bir sürü yazı başlığı mevcut.
//Bizde bunların değişebileceğini derleyiciye (.*?) ile bildirdik.
$parcala_baslik='@<h2 class="post-box-title"><a href="(.*?)">(.*?)</a></h2>@si';
//Burada da query içinden istediğimiz kısmı parçalayıp $basliklar değişkenine atıyoruz.
preg_match_all($parcala_baslik, $query, $basliklar);
$parcala_ozet='@<p>(.*?)</p>@si'; //Özet için de query içinde arayacağımız kısımı bildirdik.
preg_match_all($parcala_ozet, $query, $ozetler);
$parcala_resim='@<img width="(.*?)" height="(.*?)" src="http://www.thekodprogram.com/wp-content/uploads/(.*?)" class="(.*?)" alt="(.*?)">@si';
//Resimler için de query içinde arayacağımız kısımı bildirdik.
preg_match_all($parcala_resim, $query, $resimler);
echo "<pre>";
print_r($resimler);
"</pre>";
?>
Evet şimdi çekmek istediğimiz verileri array halinde tutmuş olduk.Sıra geldi bu array lari Json diziye atıp yollamak.
Web servisin son hali :
<?php
header('Content-Type: text/html; charset=utf-8');
$curl_handle=curl_init();
curl_setopt($curl_handle, CURLOPT_URL,'http://www.thekodprogram.com/'); //Sitemizin URL adresi
curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl_handle, CURLOPT_USERAGENT, 'deneme');
//Burada Curl çalışıyor ve linkteki bütün içerikler query değişkeninde tutuluyor.
$query = curl_exec($curl_handle);
curl_close($curl_handle);
//query değişkeninden almak istediğimiz kısmı bildiriyoruz.
//Burada (.*?) ile belirtilen yer değişecek kısım.
//Yani anasayfada bir sürü yazı başlığı mevcut.
//Bizde bunların değişebileceğini derleyiciye (.*?) ile bildirdik.
$parcala_baslik='@<h2 class="post-box-title"><a href="(.*?)">(.*?)</a></h2>@si';
//Burada da query içinden istediğimiz kısmı parçalayıp $basliklar değişkenine atıyoruz.
preg_match_all($parcala_baslik, $query, $basliklar);
$parcala_ozet='@<p>(.*?)</p>@si'; //Özet için de query içinde arayacağımız kısımı bildirdik.
preg_match_all($parcala_ozet, $query, $ozetler);
$parcala_resim='@<img width="(.*?)" height="(.*?)" src="(.*?)" class="(.*?)" alt="(.*?)">@si';
//Resimler için de query içinde arayacağımız kısımı bildirdik.
//Bize android tarafında resimlerin linkleri lazım olduğu için src kısmını full değişken olarak belirttim.
preg_match_all($parcala_resim, $query, $resimler);
//Şimdi bu değişkenlerin bize getirdiği verileri ayrı ayrı array lere atayalım.
$gelen_basliklar=array();
for($i=0;$i<count($basliklar[2]);$i++)
{
//Başlıklar için attığım resimde 2.index te başlıkların stilsiz olarak geldiği görülüyor.O yüzden 2.indexteki verileri alıyorum.
array_push($gelen_basliklar,
$basliklar[2][$i]);
}
$gelen_ozetler=array();
for($i=0;$i<count($ozetler[1]);$i++)
{
array_push($gelen_ozetler, $ozetler[1][$i]); //Ozetler için attığım resimde 1. index işimize yarıyacak.
}
$gelen_resim_linkleri=array();
for($i=0;$i<count($resimler[3]);$i++)
{
//Resimler için de linkleri aldık ve dizimize atadık.
array_push($gelen_resim_linkleri, $resimler[3][$i] );
}
$JSON["icerikler"]=array(); //JSON tipte döndüreceğimiz dizi
for($i=0;$i<count($gelen_basliklar);$i++)
{
$temp["basliklar"]=array(); //JSON dizisinin içindeki alt diziler - basliklar,ozetler,resimlink
$temp["ozetler"]=array();
$temp["resimlink"]=array();
array_push($temp["basliklar"], $gelen_basliklar[$i]);
array_push($temp["ozetler"], $gelen_ozetler[$i]);
array_push($temp["resimlink"],$gelen_resim_linkleri[$i]);
array_push($JSON["icerikler"], $temp); //Son olarak da ana json dizimize verileri entegre ettik.
}
echo json_encode($JSON,JSON_UNESCAPED_UNICODE);
?>
Web servisin JSON çıktısı da şu şekilde :
Görüldüğü üzere karmançorman görünüyo.Bunun için JSON Parser düzenleyecisi kullanırsak tag lari bulamda zorlanmayız. Ben bu adresi kullanıyorum.Burayı kullandıktan sonra web servisimizin çıktısı şu şekilde oldu :
Web kısmı uzun oldu ama tamamlandı şükür :) Şimdi Android kısmına geçelim. Tek activity kullanacağım. Birde bu activty de kullanacağım custom list için ayrı bir xml dosyamız olacak.Gerekli açıklamaları kod üzerinde yapacağım.Önce activity_main.xml kodlarını görelim :
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/veriler_listview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"></ListView>
</RelativeLayout>
Şimdi CustomList için oluşturacağımız layout dosyasını görelim :
customlist.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/tk"
android:id="@+id/logo"
android:layout_width="70dp"
android:layout_height="70dp" />
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/baslik_txt"
android:textSize="15dp"
android:textStyle="bold"
android:textColor="#f01414"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/ozet_txt"
android:textColor="#000000"
android:textSize="12dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Şimdi ise JSON verimize ulaşabilmek için istek yollayacağımız bir class hazırladım.Bu kısıma url adresimizi gönderiyoruz ve response alıyoruz.
getResponse.java
package com.thekodprogram;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class getResponse {
public getResponse()
{
//constructor
}
public String getJSONData(String url)
{
String response=null;
DefaultHttpClient httpClient=new DefaultHttpClient();
HttpGet httpGet=new HttpGet(url);
httpGet.setHeader("Content-type", "application/json");
HttpEntity httpEntity=null;
HttpResponse httpResponse=null;
try{
httpResponse=httpClient.execute(httpGet);
httpEntity=httpResponse.getEntity();
response= EntityUtils.toString(httpEntity);
}catch (Exception e)
{
e.printStackTrace();
}
return response;
}
}
Şimdi de artık MainActivity.java kısmını ineleyelim.En önemli işleri bu class da yapıyoruz :
package com.thekodprogram;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.InputStream;
import java.util.ArrayList;
public class MainActivity extends Activity {
ListView veriler_listesi;
public String Url=" web servisinizin url adresi !!! ";
ProgressDialog p;
ArrayList<String> basliklar=new ArrayList<>();
ArrayList<String> ozetler=new ArrayList<>();
ArrayList<String> resim_linkleri=new ArrayList<>();
ArrayList<Bitmap> resimler=new ArrayList<>();
MyCustomAdapter adapter;
public class ParseJSONTask extends AsyncTask<Void,Void,Void>
{
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
p.dismiss();
for(int i=0;i<resim_linkleri.size();i++)
{
getImage(resim_linkleri.get(i)); //Resimlere ait linkleri aldıktan sonra bu linklerden resimlere erişebilmek için getImage metodu oluştuduk.
Log.i("Resim İndirildi", String.valueOf(i));
}
adapter=new MyCustomAdapter(getApplicationContext(),R.layout.customlist,basliklar);
veriler_listesi.setAdapter(adapter);
}
private void getImage(String... s) {
String urldisplay = s[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
resimler.add(mIcon11); //URL den aldığımız resmi bitmap tipteki listemize ekledik.
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
p.setMessage("Lütfen Bekleyiniz...");
p.setCancelable(false);
p.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
p.show();
}
@Override
protected Void doInBackground(Void... params) {
getResponse mygetdata=new getResponse(); //Response alacağımız class türünden bir nesne oluşturuyoruz.
String jsonSTR=mygetdata.getJSONData(Url); //Ve bu nesneye web servisimizin olduğu url i yolluyoruz.Bize String şeklinde bir cevap geliyor.
try {
JSONObject jobj=new JSONObject(jsonSTR); //Bu gelen response datayı JSONObject e yükledik ve objemizi oluşturduk.
JSONArray jsonArray=jobj.getJSONArray("icerikler"); //Web servisimizin ana node olan icerikler kısmını objeden alıyoruz.Tabi hatırlarsanız bu bir JSONArray'di
for(int i=0;i<jsonArray.length();i++)
{
JSONObject contactObject=jsonArray.getJSONObject(i); //icerikler node nundan aldığımız Arrayın içerisine girmek için bir obje daha oluşturduk.
basliklar.add(contactObject.getString("basliklar").replace("–", "-")); //Fazlalık karakterleri replace ediyoruz
ozetler.add(contactObject.getString("ozetler"));
resim_linkleri.add(contactObject.getString("resimlink").replace("",""));//Fazlalık karakterleri replace ediyoruz
//Son oluşturduğumuz obje ile hemen üstteki 3 satırda basliklar,ozetler ve resimlink kısımlarını alıp List imize ekliyoruz.
Log.i("Basliklar",basliklar.get(i));
Log.i("Ozetler",ozetler.get(i));
Log.i("Linkler",resim_linkleri.get(i));
}
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
}
public class MyCustomAdapter extends ArrayAdapter<String> {
public MyCustomAdapter(Context context, int textViewResourceId, ArrayList<String> xmlList) {
super(context, textViewResourceId, xmlList);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
if (row == null) {
LayoutInflater inflater = getLayoutInflater();
row = inflater.inflate(R.layout.customlist, parent, false);
}
//CustomList içerisindeki verilerimizi kendi oluşturduğumuz MyCustomAdapter ile doldurduk.
TextView baslik_textview=(TextView)row.findViewById(R.id.baslik_txt);
baslik_textview.setText(basliklar.get(position));
TextView ozet_textview=(TextView)row.findViewById(R.id.ozet_txt);
ozet_textview.setText(ozetler.get(position));
ImageView image=(ImageView)row.findViewById(R.id.logo);
image.setImageBitmap(resimler.get(position));
return row;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
veriler_listesi=(ListView)findViewById(R.id.veriler_listview);
p=new ProgressDialog(this);
new ParseJSONTask().execute(); //Parse işlemlerini gerçekleştireceğimiz AsycnTask ı başlatıyoruz.
}
}
Manifest Dosyamızı da aşağıdaki gibi hazırlıyoruz.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thekodprogram" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
</manifest>
Biraz uzun bir yazı oldu.Bazı kısımları anlatmak benim içinde zor oldu.Umarım faydalı olur.
Bir sonraki yazıda görüşmek dileğiyle ...
Comments
Aradığım buydu çok teşekkürler. Json Parse işlemini çok güzel şekilde anlatmışsınız.
2015/08/29 15:16:35