Android WebView ile Web Uygulamaları Geliştirme

Yükleniyor
webview kullanımı

Son birkaç aydır Hobilendik‘in Android uygulamasıyla o kadar haşır neşir oldum ki, artık “WebView hakkında bir makale yazabilecek kadar öğrenmişimdir” kanısına vardım. Madem bu kanıya vardım, bir tutorial yazmaktan zarar gelmez. Hadi başlayalım.

Not: Bu yazıyı Android ve Java konusunda hiç tecrübesi olmayanlar ve yeni yeni öğrenmeye heveslenenler için yazıyorum. Bu yüzden yeterince deneyimliyseniz, bu yazı muhtemelen sizi tatmin etmeyecektir.

Hemen bakıp çıkmak isteyecekler için: Projenin kaynak kodları

Başlangıç

Ne Yapacağız?

Bu makalede adım adım bir Android web uygulamasının nasıl yapıldığını öğreneceksiniz. Bu dersteki adımları tek tek uyguladığınızda Android WebView sınıfını kullanarak bir websiteyi görüntüleyecek, burada dolaşılabilecek bir tarayıcı uygulamasına sahip olacaksınız.

Neler Gerekli?

  • Başlangıç düzeyinde programlama bilgisi
  • Eclipse & ADT eklentisi (buradan bir seferde indirip kurabilirsiniz.)
  • Test için kullanılabilecek bir Android tablet/telefon (opsiyonel)
  • Bir mobil uyumlu site. Test için m.facebook.com’u kullanabilirsiniz. Biz bu derste 1fincan.com’u kullandık.

WordPress kullanıyorsanız, siz de benim gibi WPTouch eklentisini kullanarak sitenizin mobil versiyonuna sahip olabilirsiniz.

Başlıyoruz

Eclipse’i açıp yeni bir Android projesi oluşturarak başlıyoruz. Uygulamayı oluştururken aşağıdaki resimlerdeki adımları birebir takip etmeniz faydalı olacaktır.
Not: Resimlere tıklayarak tam boyutlu görüntüleyebilirsiniz.

1. File menüsünden yeni Android projesi oluşturun. File -> New -> Other -> Android Application Project
Android WebView Dersi

2. Uygulamanızın ve Projenizin isimlerini, uygulamanın paket adını ve minimum & hedef Android versiyonlarını seçin.

Dersteki kodlarla bir çakışma olmaması için aşağıdaki resimle aynı şeyleri seçmeye özen gösterin. Özellikle paket adı aynı olmalı.

Android WebView Dersi

3. Bu adımda bir şeyi değiştirmeden olduğu gibi bırakıyoruz. Emin olmak için resme bakabilirsiniz:
Android WebView Dersi

4. Bu adımda uygulama ikonlarını ayarlamamız isteniyor. Bu bir ders olduğu için varsayılan Android logosunu kullanmaya devam edebilirsiniz.
Android WebView Dersi

5. Uygulamamızın ilk aktivitesinin nasıl olması gerektiğini seçiyoruz. Boş bir aktivite bize tam kontrol sağlayacağından bunu seçtik.
Android WebView Dersi

6. Uygulamamızın ana aktivitesinin adını seçmemiz isteniyor. Aktivite isimleri kullanıcıya görünmeyeceğinden olduğu gibi bırakıyoruz:
Android WebView Dersi

AndroidManifest’te gerekli değişiklikleri yapalım

AndroidManifest.xml, projemizin kök dizininde bulunur. Uygulamamız, aktivitelerimiz ve varsa kullandığımız servisler, izinler gibi diğer önemli şeyleri buradan belirtiriz.
Yapacağımız uygulama internet erişimi gerektirdiğinden, AndroidManifest dosyasında tek satırlık bir ekleme yaparak bu iznin gerektiğini belirtiyoruz.

<uses-permission android:name="android.permission.INTERNET" />

Bu kodu <manifest... > ve </manifest> etiketleri arasına yapıştırmamız yeterli. Emin olmak isteyenler için AndroidManifest.xml dosyamızın tamamı:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="tr.mht.webviewdersi"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="tr.mht.webviewdersi.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>

</manifest>

Bir splash resmini projeye ekleyelim

Uygulama açıldığında, sayfa yüklenene kadar bir splash resmi (örneğin logonuz) koymak gayet mantıklı olabilir. Ben bu uygulama için “paint terk” bir splash hazırladım. Siz de test için bunu kullanabilirsiniz:
Android WebView Dersi

Bu resmi bilgisayarınıza adının “splash.png” olduğundan emin olarak kaydedip Projeniz -> res -> drawable-hdpi klasörüne sürükleyip bırakın. Gelen soruya “copy files” seçeneğinin aktif olduğundan emin olarak tamam deyin.

Layout’u hazırlama

İşin sıkıcı taraflarını bitirdik. Yeni bir proje oluşturma adımlarını tamamladık ve Eclipse sağolsun yeni projemizi ve dosyalarını otomatik olarak oluşturdu. Karşımızda böyle bir ekran var muhtemelen:
Android WebView Dersi
Bu ekranda, sıkıcı görsel arayüzden kurtulmak için resimde siyah kare içine alınmış butona tıklıyoruz ve önümüze uygulama aktivitemizin layout’unun (yerleşim) 12 satırlık bir xml dosyası hali geliyor.

Bu dosyadaki tüm kodları silip aşağıdakileri yapıştırın.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mains"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
    	android:id="@+id/webviewim"
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent"
    	android:visibility="visible" />

    <ImageView
	    android:id="@+id/splash"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true"
        android:src="@drawable/splash" 
        android:visibility="visible" 
		android:contentDescription="Lütfen Bekleyin.." />
</RelativeLayout>

Burada neler yaptık?

  • İlk 6 satırda, yerleşim dosyamızın kullanacağı RelativeLayout’un özelliklerini, id’sini (kod yazarken yerleşime referans verirken bu id’yi kullanabiliriz) ve hangi aktiviteyi şekillendirdiğini belirttik.
  • 8 – 12. satırlarda WebView’imizi RelativeLayout’a yerleştirdik. “webviewim” id’sini bu WebView’e atadık. layout_width ve layout_height değerlerini fill_parent yaparak layout’ta tam alan kaplamasını sağladık. Son olarak aktivite’de görünürlüğünü visible – görünür yaptık.
  • 14 – 24. satırlar arasında splash resmimizin temel mimarisini belirledik. Yine layout_width ve layout_height ile tüm ekranı kaplattık, centerHorizontal ve centerVertical‘ile ekranın ortasına hizaladık, src ile de ImageView’imizin kaynak resmini belirledik.

activity_main.xml ile işimiz bu kadardı. Sıra geldi aktivitemizin Java ile yazacağımız asıl kodlarına.

Kodluyoruz!

XML dosyamızla aktivitemizin temellerini oluşturduk. Sıra geldi aktivitemizin ince detaylarını şekillendirmeye.

MainActivity.java’yı açın (src -> tr.mht.webviewdersi -> MainActivity.java):
Android WebView Dersi

Artık java dosyamızı düzenlemeye başlayabiliriz. Otomatik olarak oluşturulan java dosyamızdaki her şeyi siliyoruz. Ekleyeceğimiz kodlarda bolca comment (yorum) bulunduğundan ekstra açıklama yapmama gerek yok sanırım.

package tr.mht.webviewdersi;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

	private WebView WebViewim;
	private ImageView splash;

	// Uygulama açıldığında çalıştırılacak.
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        /*
         * WebViewim değişkenine, xml layout'umuzda şekillendirdiğimiz
         * WebView'i atayalım.
         */
        WebViewim = (WebView)findViewById(R.id.webviewim);
        
        /*
         * Splash'ımızı splash adında bir değişkene atayalım.
         */
        splash = (ImageView)findViewById(R.id.splash);
        
        /*
         * WebView'de tam kontrol için kendi WebViewClient'imizi
         * WebView'imize atayalım.
         */
		WebViewim.setWebViewClient(new MHTWebViewClient());
		
		// WebView ayarları.
        WebSettings websettings = WebViewim.getSettings();
        // Uygulamamıza özel user-agent.
        websettings.setUserAgentString("WebViewDersiUA");
        // Bazı ayarlar
	    websettings.setLoadWithOverviewMode(true); 
        websettings.setUseWideViewPort(true);
        // Önbelleklemeyi devredışı bırakarak daha hızlı bir uygulamaya kavuşabiliriz.
        websettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
        // JavaScript'i etkinleştir.
		websettings.setJavaScriptEnabled(true);
		websettings.setSaveFormData(false);
		websettings.setAppCacheEnabled(false);
		
		// Scroll barlar. İhtiyacınıza göre aktif edebilirsiniz.
        WebViewim.setVerticalScrollBarEnabled(false);
	    WebViewim.setHorizontalScrollBarEnabled(false);
	    
	    // URL'ye git.
	    WebViewim.loadUrl("http://1fincan.com");
    }
	
	/*
	 * Cihazda geri tuşuna basıldığında neler olacağını kararlaştır.
	 */
	@Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
		// Gezinti geçmişinde geriye gidilebiliyorsa geri git.
		if ((keyCode == KeyEvent.KEYCODE_BACK) && WebViewim.canGoBack()) {
            WebViewim.goBack();
            return true;
        } else if (keyCode == KeyEvent.KEYCODE_BACK){ // Geri gidilemiyor.
        	// Uygulamayı kapat.
        	this.finish();
        }
    	return false;
	}
	
	/*
	 * Uygulamamıza özel WebViewClient'imiz.
	 */
	private class MHTWebViewClient extends WebViewClient {
		
		/*
		 * sayfanın tamamen yüklenip yüklenmediğini anlamak için bu iki değişken
		 * bir püf noktasıdır.
		 */
		boolean yuklendi = true;
		boolean yonleniyor = false;

                // Açılan sayfanın başlığı. İşimize yarayabilir.
		public String baslik;
		
		/*
		 * Uygulamamızda tıklanan URL'leri inceler
		 * 
		 * URL bizim sitemiz dışında bir URL ise başka bir tarayıcıda açtırabiliriz. 
		 */
	    @Override
	    public boolean shouldOverrideUrlLoading(WebView view, String url) {
	    	if (!yuklendi) {
	            yonleniyor = true;
	         }
	    	yuklendi = false;
	        if (Uri.parse(url).getHost().equals("1fincan.com")) {
	            // Bu bizim siteden bir URL. Bırakalım devam etsin.
	            return false;
	        }
	        // Sitemiz dışında bir URL. Normal tarayıcıda açtır.
	        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
	        startActivity(intent);
	        return true;
	    }
	    
	    @Override
	    public void onPageStarted(WebView view, String url, Bitmap favicon)
	    {
	    	// sayfa yüklenmeye başladı.
	    	yuklendi = false;
	    }
	    
	    @Override
		public void onPageFinished(WebView view, String url)
	    {
	    	// Yüklenen sayfanın başlığı. İşinize yarayabilir.
	    	baslik = view.getTitle();
	    	
	    	if(!yonleniyor){
	             yuklendi = true;
	        }
	    	if(yuklendi && !yonleniyor){
	            // SAYFA "TAMAMEN" YÜKLENDİ
	    		
	    		/*
	    		 * Sayfa tamamen yüklendiğine göre artık splash'ı gizleyebiliriz.
	    		 * 
	    		 * Not: Bir defa gizlenince tekrar ortaya çıkmayacaktır.
	    		 */
	    		if(splash.getVisibility() == View.VISIBLE) {
	    			splash.setVisibility(View.GONE);
	    		}
	    	} else{
	             yonleniyor = false; 
	          }
	    	
		  }		
		@Override
		public void onReceivedError(WebView view, int errorCode,
				String description, String failingUrl) {
			// Bir sorun oluştuğunda kullanıcıya bildir.
			Toast.makeText(getApplicationContext(), "Bir sorun oluştu: " + description, Toast.LENGTH_SHORT).show();
		}
	}
}

Uygulamayı Test Etme

Package Explorer sekmesinden projemizi seçip Run -> Run (CTRL + F11)’i seçiyoruz ve Android Application’ı seçiyoruz. Bir android cihazı USB ile bilgisayara bağlayarak ya da sanal bir cihaz (Virtual Device) oluşturarak uygulamamızı test ediyoruz.

Ben kendi Android 2.2 telefonumda test ettim. İşte sonuçlar:
Android WebView Dersi
Android WebView Dersi

Kapanış

Umarım bu basit WebView örneği size Android geliştiriciliğinde yol gösterici olur. İşin temellerini kaptıktan sonra WebView’inize pekçok ekleme yapabilir ve daha kompleks ve kullanıcı deneyimi daha iyi olacak bir web uygulamasına sahip olabilirsiniz.

Bu ders ile ilgili anlayamadığınız noktaları, soru ve sorunlarınızı yorum kısmından yazmayı unutmayın. Görüşmek üzere.

Android WebView ile Web Uygulamaları Geliştirme” için 24 yorum

    Author’s gravatar

    Selam Abi ne olur bu kodda var ya ayri url tıklatıkda normal tarayıcı gibi açsın onu değiştirib bana göndersene ayri url tıkladıqda normal tarayıcı gibi açmasın.Please

    Cevapla
    Author’s gravatar

    shouldOverrideUrlLoading metodunu şu şekilde güncellersen tüm url’ler uygulama içinde açılır.

    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (!yuklendi) {
    yonleniyor = true;
    }
    yuklendi = false;

    // Her linki uygulamada aç:
    return false;
    }

    Cevapla
    Author’s gravatar

    Mac osx Kullanıyorum çalıştıramadım bir türlü bu projeyi

    Cevapla
    Author’s gravatar

    Merhaba,

    Sorunun işletim sistemiyle alakalı olduğunu sanmıyorum. Proje dosyasını direkt olarak indirerek mi denedin yoksa adımları tek tek takip ederek mi projeni oluşturdun? Herhangi bir hata mesajı aldın mı?

    Cevapla
    Author’s gravatar

    merhaba hocam tek tek adımları denedim sorunsuz çalıştı teşekkürler yalnız splashın süresini azaltıp yüklenme esnasında yükleniyor için progresbar nasıl koyabiliriz?

    Cevapla
    Author’s gravatar

    Bu istediğiniz şey bambaşka bir dersin konusu. Tavsiye edebileceğim makaleler:

    <a href="http://javatechig.com/android/progressbar-while-loading-webview&quot; target="_blank" rel="nofollow">ProgressBar while Loading WebView in Android</a>
    <a href="http://stackoverflow.com/questions/2537454/android-webview-progress-bar&quot; target="_blank" rel="nofollow">Android WebView progress bar</a>
    <a href="http://stackoverflow.com/questions/3903895/how-to-show-progress-bar-on-webview&quot; target="_blank" rel="nofollow">how to show progress bar on webview?</a>

    Cevapla
    Author’s gravatar

    Webview ile siteyi uygulama içerisinde açabiliyoruz. Webview içerisindeki sayfada a href kodunda tel:0XXXXXXXXXXXX var bu diğer tarayıcılarda arama yapıyor Webview’da nasıl arama yaptırabiliriz.

    Cevapla
    Author’s gravatar

    Merhaba,

    <strong>shouldOverrideUrlLoading</strong> webview’de tıklanan her linkte devreye girer ve tıklanan bağlantıyı kontrol etmemizi sağlar. Bu methodu şu şekilde düzenlersek tel: ve mailto: gibi bağlantıların sorunsuz çalışacağını düşünüyorum.

    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
    if (!yuklendi) {
    yonleniyor = true;
    }
    yuklendi = false;
    if( url.startsWith(&quot;http:&quot;) || url.startsWith(&quot;https:&quot;) ) {
    if (Uri.parse(url).getHost().equals(&quot;1fincan.com&quot;)) {
    // Bu bizim siteden bir URL. Bırakalım devam etsin.
    return false;
    } else {
    // Sitemiz dışında bir URL. Normal tarayıcıda açtır.
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    startActivity(intent);
    return true;
    }
    }

    // http ya da https değil (tel:, mailto: ya da geo:), bırakalım android sistemi kendi halletsin.
    Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    startActivity( intent );
    return true;
    }

    açıkçası kodu denemedim. kaynak: <a href="http://stackoverflow.com/a/5545463/2718799&quot; target="_blank" rel="nofollow">Android WebView “tel:” links show web page not found</a>

    Cevapla
    Author’s gravatar

    merhaba gerçekten süper bir yazı olmuş uygulamamı yaptım ama ben birde uygulama içerisinde siteye yeni bir içerik eklediğinde bildirim olarak gitmesini istiyorum bunu nasıl yapabiliriz?

    Cevapla
    Author’s gravatar

    Bunun için son yazıları RSS ya da JSON API olarak kontrol edecek bir kod, bunu gün içinde belli aralıklarla yapmanı sağlayacak AlarmManager sınıfını kullanan ayrı bir program da yazman lazım ya da üçüncü parti bir kütüphane kullanman lazım. Benim tavsiyem <a rel="nofollow" href="http://hub.buzzbox.com/android-sdk/&quot; target="_blank" rel="nofollow">Buzzbox SDK</a>’sı olur ama piyasada dediğin işi yapacak bolca kütüphane var. Seç beğen al yani :)

    Cevapla
    Author’s gravatar

    Hocam Webview ile mobil uygulamayı hazırlayıp uygulamaya başladık gayet güzel çalışıyor. Fakat site içerisinde bulunan pdf dosyasını uygulama ile açmaya çalıştığımızda dosya uzantısında hata vermektedir. Normal siteden girdiğimizde link sorunsuz çalışmaktadır. Uygulamada pdf dosyasını nasıl çalıştırabiliriz veya download yapabiliriz. Teşekkürler…

    Cevapla
    Author’s gravatar

    .pdf uzantılı dosyalarla hiç çalışmadım ama Android stock tarayıcı pdf uzantılı dosyaları nasıl işliyorsa (muhtemelen indiriyordur) webview de aynısını yapar diye tahmin ediyorum. Eğer pdfjs gibi bir kütüphaneyle pdf’yi göstermiyorsan (ve benim gibi üşengeç yapılı bir insansan) tıklanan url’yi <a href="http://developer.android.com/reference/android/webkit/WebViewClient.html#shouldOverrideUrlLoading%28android.webkit.WebView,%20java.lang.String%29&quot; title="shouldOverrideUrlLoading()" target="_blank" rel="nofollow">shouldOverrideUrlLoading()</a> methoduyla .pdf uzantılı olup olmadığını kontröl edebilir, eğer pdf uzantılıysa google docs api’siyle gösterebilirsin.

    WebView webview = (WebView) findViewById(R.id.webview);
    webview.getSettings().setJavaScriptEnabled(true);
    /* .. bişeyler .. */
    String pdf = ‘http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf’;
    webview.loadUrl(‘http://docs.google.com/gview?embedded=true&amp;amp;url=’ + pdf);

    gibi.

    Cevapla
    Author’s gravatar

    Öncelikle paylaştığınız bu yararlı bilgiler için teşekkürler.

    İlk yorumdaki arkadaşın da dediği gibi uygulamada Splash sonrası yeni bir pencerede browser açılıyor. Bu da uygulamayı anlamsızlaştırıyor. Bahsettiğiniz shouldOverrideUrlLoading metodunda değişiklik yapınca da bu sefer sitenin mobil görünümü değil de normal görünümü açılıyor ve splash ekranın ortasında kapanmadan kalıyor.

    Bu sorunun çözümü için bir kez daha kontrol edebilir misiniz lütfen?

    Cevapla
    Author’s gravatar

    Merhaba, shouldOverrideUrlLoading methodunda true döndürdüğümüzde "Bu url’yi ben inceleyip gerekeni yaptım, WebView’in bunla ilgilenmesine gerek yok" demiş oluyoruz. 108-111. satırdaki kodlarda ise "Eğer tıklanan url 1fincan.com domainindeyse WebView gerekeni yapsın (urlyi uygulama içinde açsın)" derken, 113-115. satırlarda url’yi Android sistemine göndererek gerekeni yapmasını istiyor, true döndürerek de WebView’den bu işe burnunu sokmamasını istiyoruz.

    Sizde splash sonrası site uygulamada değil de tarayıcıda açılıyorsa bunun birkaç sebebi olabilir:
    <ul>
    <li>108. satırdaki "1fincan.com"u kendi domaininizle değiştirmediniz.</li>
    <li>Sitenin mobil versiyonunu bir subdomain’de (m.site.com gibi) sunuyorsunuz ve bu yüzden getHost("site.com") false dönüyor.</li>
    </ul>

    Cevapla
    Author’s gravatar

    Merhabalar,
    Öncelikle başarılı bir şekilde uygulamayı gerçekleştirdim. Gözüme çarpan detay şu oldu eğer bir sayfaya girdiğimizde ekranı yan yatırır isek baştan yüklüyor uygulamayı. Acaba bunu nasıl düzeltebiliriz ve sizde buradaki anlatım kodlarına eklemenizi istiyorum.

    Cevapla
    Author’s gravatar

    Merhaba Mustafa. Android’de Activity’ler oryantasyon (yatay-dikey) değiştiği zaman varsayılan olarak sıfırdan başlar (onDestroy() -> onStart()). Bunun üstesinden gelmek için pek çok yöntem var. Bunlardan en kolayı <code>AndroidManifest.xml</code>’e o Activity için <code>android:configChanges="orientation|screenSize"</code> değerini eklemek. Bu değeri eklediğinde Android işletim sistemine "Bu Activity’deyken ekran dikey durumdan yatay duruma geçtiğinde (ya da tam tersi olduğunda) tüm gerekli işlemleri uygulama kendi başına halledecek, sen karışma" demiş olursun. :)

    Cevapla

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir