9 Ekim 2013 Çarşamba

Android'de Bir Uygulama Nasıl Patlatılmaz?

Android'de uygulama gelşitiriyoruz. Aklımıza gelen bütün exception'ları handle ediyoruz ama elbet bir yerde bir exception gözümüzden kaçabiliyor. Uygulama burada patladığı zaman yüzümüz kızarıyor. Artık bundan çok sıkıldığınızı biliyorum. :)

Öyleyse neden bu yakalayamadığımız exception'ları uygulamayı patlatmadan bir yere kanalize edip uygulamayı ve kullanıcıyı istediğimiz yere yönlendirmeyelim? Bu sorunun cevabını Java'nın durdurak bilmeyen nimetleri içinde bulabilmemiz mümkün.

Java bu noktada bize UncaughtExceptionHandler sınıfını sunuyor ve bununla (adı üstünde) yakalanamayan exception'ları handle etmemizi sağlıyor. Hatta bu exception'ların stack trace'ini bir String objesinde saklayabileceğinizi söylesem?

Gözlerinizin yuvalarından çıkmasına gerek yok, böyle bir şeyin olmaması Java'nın ayıbı olurdu zaten. :) Bu özelliklerle dilerseniz yayındaki bir uygulamanın sadece patlamasını önlemekle kalmaz, dilerseniz stack trace'i kendinize mail olarak atabilir, uygulamanın neresinin patladığını izleyebilirsiniz.

Sistem elbetteki bizim hayal ettiğimiz şekilde işlemiyor. Bir uygulama patladıysa onun geri dönüşü olamaz, mevcut uygulama kapatılması gerekir ki, bu en sağlıklı yöntemdir ama kullanıcı dostu değildir. Biz bu yazımızda bunu kullanıcı dostu bir hale getireceğiz.

Bunun için eğlenceli bir uygulama yapalım. İki tane activity olsun, ilk activity'e Patlat butonu koyalım ve uygulama patlasın. Fakat yazdığımız sınıflarla bu patlama kullanıcıya belli edilmesin ve ikinci activity'e geçsin. Uygulamamıza yakalanamayan exception'ı handle edecek class'ımızı ekleyelim. Adı CustomExceptionHandler.java olsun.

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;

import android.content.Context;
import android.content.Intent;
import android.os.Process;
import android.util.Log;

public class CustomExceptionHandler implements UncaughtExceptionHandler {

 private final Context context;
 
 public CustomExceptionHandler(Context context) {
  this.context = context;
 }
 
 @Override
 public void uncaughtException(Thread t, Throwable e) {
  final Writer result = new StringWriter();
     final PrintWriter printWriter = new PrintWriter(result);
     e.printStackTrace(printWriter);
     String stacktrace = result.toString();
     printWriter.close();
     
     Log.d("Stack Trace", stacktrace);
     
     Intent intent = new Intent(context, ErrorActivity.class);
     context.startActivity(intent);
     
     Process.killProcess(Process.myPid());
  System.exit(10);
 }

}

UncaughtExceptionHandler sınıfından implement edilmiş sınıfımızda, uygulama patladığı zaman uncaoughException metodu çalışacak. Burada istediğimiz şeyi yapabiliriz. Kodda görüldüğü üzere ben stack trace'i LogCat'e yazdırıyorum ve ikinci activity'miz olan ErrorActivity'ye geçiyorum. Daha sonrasında patlayan uygulamayı kill ederek tamamen kapatıyorum. Eğer uygulamada önemli static değerleriniz varsa bunlara kill etmeden önce erişebilirsiniz.

Şimdi sırasıyla ilk activity'mizin XML'ini daha sonra ikinci activity'mizin XML'inin tasarımına geçelim. İlk activity'miz activity_main.xml



    

İkinci activity'miz activity_error.xml




    

        

        

Uygulamamız açıldığında ilk activity_main XML'iyle tasarlanmış MainActivity açılacak. Burada bir patlatma butonu bulunuyor. Bu butona basıldığında NullPointerException ile patlayacak bir takım kodlar çalışacak. Patlama işlemi gerçekleşince CustomExceptionHandler sınıfımız bu exception'ı yakalayacak ve konsola yazdıracak, ardından activity_error XML'iyle tasarlanmış ErrorActivity'miz açılacak.

Şimdi bu iki activity'ni Java tarafındaki sınıflarının içini dolduralım. İlk olarak MainActivity'.java

import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(this));
 }

 public void onPatlatClick(View v) {
  String funye = null;
  if(funye.equals("BOM")) {
   
  }
 }
}

Burada dikkat etmeniz gereken husus onCreate metodunda çağırdığım setDefaultUncaughtException'dır. Bu kod, uygulamanın başında çağrılmıştır ve yakalanamayan exception'ları yakalamak için CustomExceptionHandler sınıfımızı aktif hale getirmiştir. Bu koddan itibaren olabilecek bütün yakalanamayan exception'lar bu sınıfımıza düşecektir. Öte yandan. onPatlatClick metodumuzda Patlat butonuna basıldığında olacak işlemlerin implementasyonu yapılmıştır. Uygulama tam burada patlamaktadır ve NullPointerException fırlatır.

İkinci activity'miz ErrorActivity.java da aşağıdaki gibidir.

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class ErrorActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_error);
 }
 
 public void onAnaSayfaClick(View v) {
  Intent intent = new Intent(ErrorActivity.this, MainActivity.class);
  startActivity(intent);
  finish();
 }
}

Bu activity uygulama patladıktan sonra açılır. Activity'de ilk activity'mize geri dönüş yapabileceğimiz bir buton bulunur ve bu butona basıldığında bu activity sonlandırılır ve uygulama ilk açıldığı haline döner.

Böylece uygulamayı kullanıcıya 'Durduruldu' mesajı vermeden patlatır ve eski haline geri dönmesini sağlayabiliriz. Bu özellikle uygulamaya hiç bir şey olmamış gibi öncekini öldürüp farklı bir kanaldan yeni bir yaşam döngüsüne sokabilir ve kullanıcıya bunu farkettirmezsiniz. Dahası dilerseniz uygulamanın patladığı yerin stack trace'ini kendinize mail atabilir ve anında müdahale edebilirsiniz.

Hiç yorum yok:

Yorum Gönder