İçerik: Android üzerinden webservislere erişim, gelen yanıtın parse edilmesi ve kullanılması.
Bu seferki yazım bir yıldan fazla zamandır sıkça kullandığım, Android üzerinden SOAP [0] webservislerine bağlanma ve kullanma konusunda kolaylıklar sağlayan ksoap2 [1] hakkında olacak. E-mail doğrulaması yapan public bir webservisi kullanan örnek bir uygulama üzerinden gideceğim.
Kullanacağım webservisi basit göründüğü için aşağıdaki olarak seçtim (google’da karşıma ilk çıkanlardan biri):
http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx?op=VerifyEmail
Metodların tam listesi:
http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx
Ve servis tanımlaması:
http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx?WSDL
Kullanacağımız metoddan bahsedecek olursak, bir email ve lisans anahtarını parametre olarak alıyor, arka planda kontrolünü yapıyor ve işlem hakkında 4 farklı bilgiyi bize veriyor (ResponseText, ResponseCode, LastMailServer, GoodEmail). Yapmak istediğim uygulama da verdiğim email ve lisans anahtarı bilgilerini bu servise gönderen ve gelen yanıtı aldıktan sonra parse edip, her bir bilgiyi ekranda ayrı ayrı gösterecek.
Servisi test etmek için url’de bir arayüz var ama böyle bir arayüze sahip olmayan servisler için test aracı olarak soapUI [2] ya da SOAPSonar [3] kullanılabilir. SOAPSonar Personal Edition’da test ettiğimde gönderilen istek aşağıdaki gibi oldu:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://ws.cdyne.com/">
<soap:Body>
<tns:VerifyEmail>
<tns:email>oguzozkeroglu@hotmail.com</tns:email>
<tns:LicenseKey>test</tns:LicenseKey>
</tns:VerifyEmail>
</soap:Body>
</soap:Envelope>
Aldığım yanıt ise aşağıdaki gibi:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<VerifyEmailResponse xmlns="http://ws.cdyne.com/">
<VerifyEmailResult>
<ResponseText>Verified Email Address</ResponseText>
<ResponseCode>2</ResponseCode>
<LastMailServer>mx2.hotmail.com</LastMailServer>
<GoodEmail>true</GoodEmail>
</VerifyEmailResult>
</VerifyEmailResponse>
</soap:Body>
</soap:Envelope>
Kullanmadığım mail adresimin verified olmasını görmek sevindirdi açıkçası :) Şimdi aynı işlemleri bir Android projesi ile yapalım ve gelen yanıtı anlamlı hale getirip XML taglari arasındaki bilgileri birbirinden ayırıp ekranda gösterelim.
Öncelikle Eclipse’te bir Android projesi yaratalım. Kullanacağımız hiçbir metod ve özellik android-4 üzeri bir sürüm gerektirmiyor, o yüzden minimum ve target sdk seçenekleri 1.6 tutulabilir (en yenisi olsun diye kasmaya gerek yok :)
Yapacağımız ilk iş Manifest dosyasına internete erişim iznini eklemek olursa sonradan gerçekleşmesi muhtemel bir hatayı (java.net.SocketException) en baştan önlemiş oluruz. Eğer uygulamamız internet ile iletişime geçecekse aşağıdaki izni Manifest dosyamıza eklemiş olmamız gerekiyor.
<uses-permission android:name="android.permission.INTERNET" />
Şimdi de gelen yanıttaki bilgileri tutacağımız nesne için bir class yazalım. Gelen XML’deki ada göre bir isimlendirme yaptım, o kısım için daha kolay akılda kalacak ya da daha anlamlı bir isim seçilebilir.
public class VerifyEmailResult {
private String responseText;
private int responseCode;
private String lastMailServer;
private boolean goodEmail;
public VerifyEmailResult() {
super();
}
public VerifyEmailResult(String responseText, int responseCode,
String lastMailServer, boolean goodEmail) {
super();
this.responseText = responseText;
this.responseCode = responseCode;
this.lastMailServer = lastMailServer;
this.goodEmail = goodEmail;
}
public String getResponseText() {
return responseText;
}
public void setResponseText(String responseText) {
this.responseText = responseText;
}
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
public String getLastMailServer() {
return lastMailServer;
}
public void setLastMailServer(String lastMailServer) {
this.lastMailServer = lastMailServer;
}
public boolean isGoodEmail() {
return goodEmail;
}
public void setGoodEmail(boolean goodEmail) {
this.goodEmail = goodEmail;
}
@Override
public String toString() {
return "VerifyEmailResult [responseText=" + responseText
+ ", responseCode=" + responseCode + ", lastMailServer="
+ lastMailServer + ", goodEmail=" + goodEmail + "]";
}
}
Daha sonra bu classtan oluşturduğumuz nesnenin içini dolduracak, aslında yapmamız gereken işin çoğunu yapacak (webservis ile bağlantı kurup, parametrelerimizi karşıya gönderecek, ordan yanıt bekleyip aldığı yanıtı parse edip sonrasında bilgileri istediğimiz formatta bize verecek) olan classı yazalım.
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.HttpTransportSE;
public class EmailValidator {
private static final String METHOD_NAME = "VerifyEmail";
private static final String NAMESPACE = "http://ws.cdyne.com/";
private static final String SOAP_ACTION = "http://ws.cdyne.com/VerifyEmail";
private static final String URL = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx";
public static VerifyEmailResult verifyEmail (String eMail, String licenseKey) {
VerifyEmailResult object = new VerifyEmailResult();
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("email", eMail);
request.addProperty("LicenseKey", licenseKey);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject response = (SoapObject) envelope.getResponse();
if (response.hasProperty("ResponseText")) {
if (response.getPropertyAsString("ResponseText") == null) {
object.setResponseText(null);
} else {
object.setResponseText(response.getPropertyAsString("ResponseText"));
}
}
if (response.hasProperty("ResponseCode")) {
if (response.getPropertyAsString("ResponseCode") == null) {
object.setResponseCode(-1);
} else {
object.setResponseCode(Integer.parseInt(response.getPropertyAsString("ResponseCode")));
}
}
if (response.hasProperty("LastMailServer")) {
if (response.getPropertyAsString("LastMailServer") == null) {
object.setLastMailServer(null);
} else {
object.setLastMailServer(response.getPropertyAsString("LastMailServer"));
}
}
if (response.hasProperty("GoodEmail")) {
if (response.getPropertyAsString("GoodEmail") == null) {
object.setGoodEmail(false);
} else {
object.setGoodEmail(Boolean.parseBoolean(response.getPropertyAsString("GoodEmail")));
}
}
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
}
Bu classı yazdığımızda IDE org.ksoap2.* importlarını yapamadığı için uyarı verecektir çünkü standart Java ve Android SDK içinde o classlar bulunmamaktadır. Peki şimdi ne yapmak gerekir? Yazının konusu olan ksoap2 kütüphanesini indirip [4] projemize eklemeliyiz. Benim indirip kullandığım dosyanın ismi: ksoap2-android-assembly-2.6.0-jar-with-dependencies.jar. JAR dosyasını projeme eklemek için de kullandığım yöntem: Proje klasörü içinde libs isminde bir klasör oluşturup projeye eklemek istediğim jar dosyalarını oraya attıktan sonra Eclipse Package Explorer’da proje üzerinde sağ click -> Properties -> Java Build Path -> Libraries -> Add JARs -> sonrasında da klasörün içindeki istenilen JAR dosyalarını eklenmesi..
Bu işlemler sıkıntısız şekilde tamamlandıktan sonra projede herhangi bir hata kalmaması gerekiyor.
Şimdi yukardaki kodda ne yaptığımıza gelelim.
private static final String METHOD_NAME = "VerifyEmail"; private static final String NAMESPACE = "http://ws.cdyne.com/"; private static final String SOAP_ACTION = "http://ws.cdyne.com/VerifyEmail"; private static final String URL = "http://ws.cdyne.com/emailverify/Emailvernotestemail.asmx";
Burda metod ismi, namespace, soap action ve servisin bulunduğu adresi belirttik.
VerifyEmailResult object = new VerifyEmailResult();
Parse edilen verileri tutacağımız geçici nesnemizi yarattık.
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
request.addProperty("email", eMail);
request.addProperty("LicenseKey", licenseKey);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;
Burda da servise yapacağımız isteği oluşturup parametreleri ekliyoruz. Sonrasında SOAP envelope nesnesini oluşturup, bir .net servisini çağıracağımızı belirtiyoruz.
androidHttpTransport.call(SOAP_ACTION, envelope); SoapObject response = (SoapObject) envelope.getResponse();
Burda servisi çağırıp gelen yanıtı SoapObject türünden bir nesneye atıyoruz.
XML’den farklı olarak ksoap2 nesneleri kendine özel bir formatta tutulur ve bunlar üzerinde işlem yapılır. Örneğin yukarıda XML halini yazmış olduğum isteğe karşılık gelen bizim request nesnemizin içeriği aşağıdaki gibi olacaktır:
VerifyEmail{
email=oguzozkeroglu@hotmail.com;
LicenseKey=test;
}
Gelen yanıta karşılık gelen response nesnemizin içeriği de aşağıdaki gibi olacaktır:
anyType{
ResponseText=Verified Email Address;
ResponseCode=2;
LastMailServer=mx4.hotmail.com;
GoodEmail=true;
}
Bu format parse işlemlerinde kolaylık sağlıyor. anyType XML’deki root’a yani VerifyEmailResult‘a karşılık geliyor gibi düşünebiliriz. Diğerleri zaten isminden anlaşılıyor. Herhangi bir özelliğe erişmek için
response.getPropertyAsString("OzellikIsmi");
kullanılabilir. (response.getProperty() ise geri bir String değil SoapObject döndüreceği için ekranda görüntülemede ya da nesnenin özelliklerini atamada sıkıntı çıkarabilir. Özelliğe o nesneden ulaşmak istediğimizde ise aşağıdaki gibi bir yapı kullanabiliriz.
String.valueOf(response.getProperty("OzellikIsmi"));
ksoap2′nin 2.5.8 sürümüne kadar böyle erişiliyordu. Parse işlemi için response nesnemizin öyle bir özelliği varsa ve null değilse kontrollerinden sonra atama yapıp en son nesneyi geri döndürüyoruz.
if (response.hasProperty("ResponseText")) {
if (response.getPropertyAsString("ResponseText") == null) {
object.setResponseText(null);
} else {
object.setResponseText(response.getPropertyAsString("ResponseText"));
}
}
/** ... */
Bu iki classı yazdıktan sonra ana sayfaya ait olan layout sayfasına (XML), bir adet Button ve 4 adet TextView ekledim. İşimiz tasarımla değil arka plandaki işlerle olduğu için tasarıma pek takılmayalım, dandik durduğunun farkındayım :)

Artık elimizdeki malzemeleri kullanmanın zamanı geldi. Ana sayfada aşağıdaki global tanımlamaları ekledim
VerifyEmailResult object = null;
final String eMail = "oguzozkeroglu@hotmail.com";
final String licenseKey = "test";
mThread thread = null;
Butonu tanımlayıp işlevsellik kazandıralım
Button btnInvokeService = (Button) findViewById(R.id.btnInvoke);
btnInvokeService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
thread = new mThread();
thread.start();
}
});
Butona basındığında tanımladığımız thread çalışacak. Peki thread ne yapacak?
private class mThread extends Thread {
@Override
public void run() {
object = EmailValidator.verifyEmail(eMail, licenseKey);
handler.sendEmptyMessage(0);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
thread.interrupt();
setTexts();
}
};
}
Çağırdığımızda EmailValidator classımızın verifyEmail metodunu çağıracak ve işlem bittikten sonra setTexts metodu çağrılacak. O metod ne yapacak?
private void setTexts() {
TextView tv1 = (TextView) findViewById(R.id.tv1);
TextView tv2 = (TextView) findViewById(R.id.tv2);
TextView tv3 = (TextView) findViewById(R.id.tv3);
TextView tv4 = (TextView) findViewById(R.id.tv4);
tv1.setText("ResponseText ->" + object.getResponseText());
tv2.setText("ResponseCode ->" + object.getResponseCode());
tv3.setText("LastMailServer ->" + object.getLastMailServer());
tv4.setText("GoodEmail ->" + object.isGoodEmail());
}
Basit bir şekilde servisten dönen bilgileri oluşturduğumuz TextView‘lara atayacak ve ekranda görünmesini sağlayacak. Butona basıldıktan kısa bir süre sonra aşağıdakine benzer bir şeyler ortaya çıkmalı:

Orada görünen ResponseText ve ResponseCode listesinin tamamını metodlardan biri veriyor. Ben çıktıyı buraya da yazayım.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ReturnCodesResponse xmlns="http://ws.cdyne.com/">
<ReturnCodesResult>
<anyType xsi:type="xsd:string">0-Invalid Email Address</anyType>
<anyType xsi:type="xsd:string">1-Not Used</anyType>
<anyType xsi:type="xsd:string">2-Verified Email Address (Treat as a good email)</anyType>
<anyType xsi:type="xsd:string">3-Mail Server will accept email (Treat as a good email)</anyType>
<anyType xsi:type="xsd:string">4-User not found</anyType>
<anyType xsi:type="xsd:string">5-Email Domain not found</anyType>
<anyType xsi:type="xsd:string">6-Not Used</anyType>
<anyType xsi:type="xsd:string">7-SMTP/Timeout Error (Treat as a good email)</anyType>
<anyType xsi:type="xsd:string">8-Domain valid. Email server(s) down</anyType>
<anyType xsi:type="xsd:string">9-License Key allowance exceeded</anyType>
</ReturnCodesResult>
</ReturnCodesResponse>
</soap:Body>
</soap:Envelope>
Umarım yararlı bir yazı olmuştur. Kullandığım yöntemler bu işi yapmanın en iyi yöntemleri olmayabilir, araçlar ve kullandığım terimler doğru olmayabilir ama bu haliyle benim işimi gördüler bugüne kadar. Herhangi bir eleştiri / düzeltme / ekleme yapmak isteyen olursa konuya yorum bırakabilir ya da mail atabilir.
*0 -> http://en.wikipedia.org/wiki/SOAP
*1 -> http://code.google.com/p/ksoap2-android/
*2 -> http://www.soapui.org/
*3 -> http://www.crosschecknet.com/products/soapsonar.php
*4 -> http://code.google.com/p/ksoap2-android/wiki/HowToUse?tm=2
Android cihazın wifi durumuna erişip, ağa bağlı mı değil mi kontrolü yapan ve wifi durumunu etkinliştirip / devre dışı bırakan basit bir sayfa için aşağıdaki metodlar kullanılabilir. Metodların çalışabilmesi için wifi durumuna erişim ve wifi durumunu değiştirebilme izinlerini manifest dosyasına eklemek gerekir.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
WifiManager’dan bir nesne oluşturup, bu nesnenin özelliklerini ve metodlarını kullanacağız.
WifiManager wifi = null;
Nesneyi global tanımlamakta fayda var. İki metod içerisinde de bu nesne kullanılacak.
Aşağıdaki metod çağrıldığında önce wifi durumu kontrol ediliyor. Eğer aktif ise önce devre dışı bırakılıyor, sonrasında kullanıcıya wifi’ın devre dışı bırakıldığına dair bir uyarı mesajı gösteriliyor. Eğer devre dışı bırakılıyorsa sadece kullanıcıya wifi’ın devre dışı bırakılıyor olduğuna dair bir mesaj gösteriliyor. Diğer durumlarda ise -örneğin wifi zaten devre dışı ise- hiçbir iş yapılmıyor.
private void disableWifi() {
try {
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
wifi.setWifiEnabled(false);
showNotification("Wifi is disabled!");
} else if (wifi.getWifiState() == WifiManager.WIFI_STATE_DISABLING){
showNotification("Wifi is disabling!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
Aşağıdaki metod da yukarıdakinin tam tersi işleri yapıyor.
private void enableWifi() {
try {
wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifi.getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
wifi.setWifiEnabled(true);
showNotification("Wifi is enabled!");
} else if (wifi.getWifiState() == WifiManager.WIFI_STATE_ENABLING){
showNotification("Wifi is enabling!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
Metodlarda kullanılan showNotification() metodu ise sadece parametre olarak aldığı stringi Toast mesajı olarak ekranda gösteriyor. İçeriği de aşağıdaki gibi:
private void showNotification(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
Üzerinde çalıştığım bir Android projesinde EditText alanına girilen e-mail değerinin gerçekten de bir e-mail adresi mi olduğunun kontrol edilmesi gerekiyordu. Bunun için aşağıdaki kodu bulup kullandım.
boolean isEmailValid(String email) {
String expression = "^[\\w\\-]([\\.\\w])+[\\w]+@([\\w\\-]+\\.)+[A-Z]{2,4}$";
CharSequence inputStr = email;
Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(inputStr);
return matcher.matches();
}
Girilen tüm değerleri doğru test ediyor mu bilemem ama benim işimi görecek kadar iyi çalışıyor. Aşağıdaki kod bloğu ile test ettiğimde;
ArrayList<String> addresses = new ArrayList<String>();
addresses.add(" ");
addresses.add("test");
addresses.add("test.com");
addresses.add("test@com");
addresses.add("test@test.com");
addresses.add("test@test.com.");
addresses.add("test@test.com.tr");
addresses.add("test.test@test.com.tr");
addresses.add("test@türkçe.karakter.tr");
for (int i = 0; i < addresses.size(); i++) {
System.out.println(addresses.get(i) + " :: "
+ isEmailValid(addresses.get(i)));
}
şu aşağıdaki çıktıyı verdi:
:: false
test :: false
test.com :: false
test@com :: false
test@test.com :: true
test@test.com. :: false
test@test.com.tr :: true
test.test@test.com.tr :: true
test@türkçe.karakter.tr :: false
Yeniden anlamış olduk ki regular expressions hayat kurtarır :)
Kaynak: zparacha.com
İlki bir önceki yazım olan ve yalnızca 2 yazıdan oluşan muhteşem yazı dizime (Eclipse & Android SDK kullanırken karşılaştığım hatalar) kaldığım yerden devam ediyorum. Bu sefer uygulamayı cihaz üzerinde çalıştırmak istediğimde aldığım hata ve google amcanın yardımıyla kavuştuğum çözümden bahsedeceğim. Hata aşağıdaki gibi:
Android Launch!
adb is running normally.
Performing com.test.Splash activity launch
Uploading Test.apk onto device 'HT9A4LV01328'
Failed to install Test.apk on device 'HT9A4LV01328': timeout
Launch canceled!
ADB çalışıyor, upload tamam ama uygulama yüklenemeden timeout’a düşüyor. Çözüm için de Eclipse -> Preferences -> Android -> DDMS -> ADB connection time out (ms) yolunu izliyoruz ve orda default 5.000 olarak gelen değeri biraz artırıyoruz. (misal 10.000, yetmezse 15.000 vs)

Yeniden denediğimizde Console çıktısını aşağıdaki gibi görüyorsak olay tamamdır.
Android Launch!
adb is running normally.
Performing com.test.Splash activity launch
Uploading Test.apk onto device 'HT9A4LV01328'
Installing Test.apk...
Success!
Starting activity com.test.Splash on device HT9A4LV01328
Android SDK ve Eclipse ADT Plugin’ini güncelledikten sonra daha önce yaratmış olduğum AVD’lerden bir tanesini çalıştırmak istediğimde aşağıdaki gibi bir hata aldım.
invalid command-line parameter: Files.
Hint: use '@foo' to launch a virtual device named 'foo'.
please use -help for more information

Google amcaya sordum “n’oluyoruz la?” diye, aynı problemle karşılaşmış insanlar gösterdi bana. Meğerse güncellemeden sonra Eclipse artizlik yapıp Windows’un boşluk, parantez vs karakterleri içeren dosya yollarını beğenmiyormuş. O güne kadar sorunsuz çalışan kısım, yani Eclipse -> Window -> Preferences -> Android -> SDK Location kısmında yazılı olan
C:\Program Files (x86)\Android\android-sdk
artık çalışmayacakmış.

“E çözüm neymiş peki?” diye baktığımda da o yolu şu aşağıdakilerden biri ile değiştirmek olduğunu öğrendim.
C:\PROGRA~1\Android\android-sdk
C:\PROGRA~2\Android\android-sdk
İlki şuna;
C:\Program Files\Android\android-sdk
ikincisi de şuna;
C:\Program Files (x86)\Android\android-sdk
ilaçmış. İlgililere duyrulur.
Android’in veri saklama yöntemleri ile alakalı daha önce Android :: Shared Preferences yazısını yazmıştım. O listedeki external storage cihazın harici hafızasına, yani şimdilik sd karta tekabül ediyor.
Üzerinde çalıştığım projelerin birinde mp3 dosyalarını saklamam gerekiyordu. Sayısı birden fazla ve her birinin ortalama boyutu 10 mb civarında mp3 dosyalarını dahili hafızaya ya da uygulama paketi içinde bir yerlere yazsam kısa süre sonra cihaz kullanılmaz hale gelebilir. Bu durumda çözüm olarak dosyaları sd kart üzerine yazmaya karar verdim (Umarım doğru bir karar vermişimdir :)
Başta direkt sd kart üzerine yazıp uygulamayı çalıştırdım ama kısa süre sonra kart çöplüğe döndü. Her şeyi ana dizin içine atıyordum. İşte tam burda kart üzerinde bir klasör oluşturma ve dosyaları oraya yazma / oradan okuma zorunda kaldım. Bu yazıda da bu olayı nasıl yaptığımı anlatmaya çalışacağım.
Bunun için Java’nın “File” class’ından bir obje yaratıp, parametre olarak yol + klasör ismi verdim ve sonrasında file.mkdir() metodu ile klasörü oluşturdum. Kod aşağıdaki gibi:
File mFile = new File("/sdcard/altKlasor");
mFile.mkdir();
Tabi bu kodun çalışması için yine her zamanki gibi AndroidManifest.xml dosyasına harici hafızaya yazma iznini eklememiz gerekiyor.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Bu sayede direkt sd kart altında klasörü oluşturduk. Aşağıda Eclipse’teki File Explorer’ın kod çalışmadan önceki ve sonraki hali var.
Önce:

Sonra:

Kodu çalıştırdık işimizi gördük ama burda ufak bir sıkıntı var. Sd kartın yolunu elle girdik. İlerde yolun değişebilmesi ya da sd kart yerine başka bir harici hafıza kullanılabilmesi durumlarına karşılık daha iyi bir yöntem kullanmak gerekti. Bunun için de harici hafızanın direkt yolunu alan aşağıdaki kodu buldum.
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
Bu şekilde biraz daha bağımsızlık ve esneklik kazanmış olduk. Dosyayı oluşturan kodun tamamı aşağıdaki gibi şekillendi.
String strNewFolder = "/altKlasor"; String extStorageDirectory = Environment.getExternalStorageDirectory().toString(); File mFile = new File(extStorageDirectory + strNewFolder); mFile.mkdir();
Belki birinin daha işine yarar..
WebView içinde bir web sayfasını göstermek için aşağıdaki kod kullanılıyor.
WebView wv;
wv = (WebView) findViewById(R.id.webview);
wv.loadUrl("http://www.google.com");
Tabi bunu kullanabilmek için uygulamamıza internete erişim iznini vermemiz gerekiyor. Bunun için de AndroidManifest.xml dosyası içinde uygun yere aşağıdaki satırı ekliyoruz.
<uses-permission android:name="android.permission.INTERNET" />
Çalıştırdığımızda aşağıdaki gibi bir görüntü elde ediyoruz.

Buraya kadar bir sıkıntı yok zaten bilinen şeyler. Peki kendi hazırladığımız bir html sayfasını nasıl gösteririz?
Bunun için html içeriğimizi oluşturup bir stringe atıyoruz ve WebView içinde o stringi gösteriyoruz.
String strHtml = "<html><head></head>" + "<body text=\"#444444\" bgcolor=\"#CCCCCC\">" + "<br /><br /><center><h2>" + "Static html content in Android" + "</h2></center></body></html>"; wv.loadData(strHtml, "text/html", "UTF-8");

Artık internet erişimine gerek kalmadığı için Manifest dosyamızdan o izni kaldırabiliriz. Bu string içinde CSS de kullanılabilir. Bunlar yeterli değil, JavaScript de olsun diyorsanız aşağıdaki satırı WebView tanımlamasında sonra eklemeniz gerekir.
wv.getSettings().setJavaScriptEnabled(true);

Örnek uygulamada kullandığım java dosyası:
package com.oguz.example;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebView;
public class WebViewTest extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
setContentView(R.layout.webwiew_test);
WebView wv = (WebView) findViewById(R.id.webkitWebView1);
String strHtml = "<html><head></head>"
+ "<body text=\"#444444\" bgcolor=\"#CCCCCC\">"
+ "<br /><br /><center><h2>"
+ "Static html content in Android</h2>"
+ "<script type=\"text/javascript\">"
+ "document.write(Date());</script>"
+ "</center></body></html>";
wv.getSettings().setJavaScriptEnabled(true);
wv.loadData(strHtml, "text/html", "UTF-8");
}
}
XML dosyası ise:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <android.webkit.WebView android:id="@+id/webkitWebView1" android:layout_width="fill_parent" android:layout_height="fill_parent"> </android.webkit.WebView> </LinearLayout>



