BG MVC Model View Controller eğitim serisi yayında...

Ana sayfa > Programlama > Android Programlama > Programlar arası işlem

Programlar arası işlem

Bir Android programında yer alan aktiviteler arasında geçiş yapmak için bir Intent nesnesini geçiş yapacağınız aktivitenin sınıf adı ile birlikte kullanabilirsiniz. Bu durumda Intent nesnesi direk olarak kullanılmış olur.

Eğer Intent nesnesini başka bir programda yer alan belirli bir bileşeni çalıştırmak için kullanırsanız, bu durumda Intent nesnesi dolaylı olarak kullanılmış olur. Bu durumda, sistem kullanıcının talebinizi karşılayabilecek tüm bileşenleri bir seçenek olarak sunar. Kullanıcı bu seçeneklerden kendisi için uygun olanı seçer ve kullanır.

Bu bölümde, bir Android uygulamasının diğer uygulamaları kullanma ve sonuç alma işlemleri ile kendi uygulamalarımızın diğer uygulamaların isteklerine karşılık verir hale getirme işlemlerini incelemeye çalışacağız.

Bir Android programını kullanırken, gerçekleştirmek istediğiniz işlem gerektirdiğinde, başka bir Android programını kullanabilirsiniz. Bu tür bir işlemi gerçekleştirmek için programlarımızda Intent nesnesini dolaylı olarak kullanmamız gerekir.

Dolaylı Intent oluşturma

Dolaylı Intent bildirimlerinde; başlatılacak bileşenin sınıf adı değil, yapılacak işlemin tanımı yapılır. İşlem kullanıcı tarafından yapılmak istenen görüntüleme, düzenleme, gönderme veya elde etme gibi herhangi bir işi içerebilir. Intent'ler yapılacak işlemle ilgili olarak görüntülemek istediğiniz web adresi veya göndermek istediğiniz mesaj metni gibi bilgileri de içerir.

Eğer intent ile birlikte bir Uri veri türü tanımlanırsa, intent ile birlikte yapılacak olan işlemi ve veriyi tanımlayabilirsiniz.

Aşağıda telefon numarası çevirme, web sayfası gösterme ve e-posta gönderme amacıyla oluşturulmuş dolaylı Intent tanımlamaları yer almaktadır:

Telefon numarası çevirme

Uri number = Uri.parse("tel:3522147");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

Web sayfası görüntüleme

Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

E-posta gönderme

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// Intent URI değeri olmadığından, "text/plain" MIME türü tanımlanır.
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
// E-posta alıcıları
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"info@mysite.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "E-posta başlığı");
emailIntent.putExtra(Intent.EXTRA_TEXT, "E-posta içeriği");

Yukarıda gösterilen e-posta gönderme gibi bazı intent'lere karakter metinleri gibi farklı veri türleri aktarmak gerekebilir. Bu verileri aktarmak için putExtra() metodu kullanılır.

Ön tanımlı olarak, sistem intent ile birlikte tanımlanan URI değerine bakarak uygun MIME türünü belirler. Eğer, intent ile bir URI değeri tanımlanmadığında, intent ile ilgili veri türünü tanımlamak için setType() metodu kullanılır. MIME türünü tanımlamak hangi tür aktivitelerin intent çağrısına karşılık vereceğini belirler.

Intent için kullanılacak uygulama kontrolü

Dolaylı bir intent kullanmadan önce, intent çağrısına karşılık vererek gereken işlemi yapabilecek bir uygulama olup olmadığını kontrol etmeniz gerekir. Aksi takdirde; intent için işlem yapabilecek bir uygulama olmadığında, uygulamanız düzgün çalışmaz.

Intent için gerekli işlemleri yapabilecek bir aktivite olup olmadığını kontrol etmek için, queryIntentActivities() metodunu kullanarak intent için işlem yapabilecek aktivitelerin bir listesini elde edebilirsiniz. Eğer liste boş değilse, intent'i rahatlıkla kullanabilirsiniz.

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent, 0);
boolean isIntentSafe = activities.size() > 0;

isIntentSafe değeri doğru olması, intent için işlem yapabilecek en az bir uygulama olduğunu, yanlış olması ise herhangi bir uygulama omadığını gösterir.

Kullanıcı intent ile ilgili özelliği kullanmadan önce devre dışı bırakabilmeniz için bu kontrolü aktivite ilk başlatıldığında yapmanız daha uygun olur.

Intent ile aktivite başlatma

Intent oluşturduktan ve gerekli bilgileri ayarladıktan sonra, startActivity() metodu ile intent çağrısı yapılır. Eğer sistem intent için işlem yapabilecek birden fazla aktivite olduğunu tespit ederse, kullanıcının içinden istediğini seçebilmesi için bir diyalog kutusunu ekrana getirir. Intent için işlem yapabilecek sadece bir aktivite varsa, sistem direk olarak aktiviteyi çalıştırır.

// Intent oluşturma
Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

// Intent için işlem yapabilecek uygulama kontrolü
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(webIntent, 0);
boolean isIntentSafe = activities.size() > 0;
  
// Intent başlatma
if (isIntentSafe) {
    startActivity(webIntent);
}

Yukarıdaki satırlarda yer alan intent'i çalıştırdığınızda, eğer intent için işlemyapabilecek birden fazla aktivite varsa, tüm aktviteleri listeleyen kutunun altında bu işlem için ön tanımlı olarak kullanılacak aktiviteyi seçmeyi sağlayan bir kontrol kutusu bulunur. Bir intent başlatıldığında hep aynı uygulamanın işlem yapmasını isterseniz bu yöntem oldukça faydalıdır. Ancak, intent her çalıştığında farklı bir uygulama seçmenizi sağlayacak ve ön tanımlı uygulama seçimi olmayan bir diyalog kutusu kullanmak isterseniz, createChooser() metodunu kullanarak bir intent oluşturabilir ve startActivity() metodunu çalıştırabilirsiniz:

// Intent oluşturma
Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

// Intent için işlem yapabilecek uygulama kontrolü
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(webIntent, 0);
boolean isIntentSafe = activities.size() > 0;
  
// Intent başlatma
if (isIntentSafe) {
    // UI metin değeri için karakter dizisi kaynaklarını kullanın.
    String title = getResources().getText(R.string.chooser_title);
    // Uygulama seçme diyalog kutusunu çağırır.
    Intent chooser = Intent.createChooser(webIntent, title);
    
    startActivity(chooser);
}

Bir aktiviteden sonuç alma

Bir aktivite başlatmak için startActivity() yerine startActivityForResult() metodunu kullanarak bir sonuç geri alabilirsiniz.

Bu durumda, çağrılan aktivite bir sonuç geri verecek şekilde oluşturulmuş olmalıdır. Aktivite bir intent yoluyla çağrıldığında, sonucu farklı bir Intent nesnesi olarak gönderir. Çağıran aktivite çağırdığı aktivite tarafından geri verilen sonucu onActivityResult() metodu içinde alır.

startActivityForResult() metodunu direk veya dolaylı intent'lerle birlikte kullanabilirsiniz. Kendi programınız içindeki aktivitelerden birini sonuç alabilecek şekilde çalıştırmak için intent'leri direk olarak kullanmanız gerekir.

startActivityForResult() metodunu kullandığınızda integer bir değeri bu metoda argüman olarak geçirmeniz gerekir. Bu değer talebinizi gösteren bir koddur. Sonuç intent'ini aldığınızda, onActivityResult() metodu içinde talep kodu bulunduğundan, programınız sonucun hangi talebe ait olduğunu belirler ve ona göre işlem yapar.

Aşağıdaki kod kullanıcının bir kişiyi seçmesini sağlayacak aktiviteyi başlamasını sağlar:

static final int PICK_CONTACT_REQUEST = 1;  // Talep kodu
...
private void pickContact() {
   Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts"));
   // Kişileri ve telefon numaralarını gösterir.
   pickContactIntent.setType(Phone.CONTENT_TYPE); 
   startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}

Bir program tarafından sonuç elde edecek şekilde intent kullanılarak çağrılan aktivitenin çalışması bittiğinde ve bir değer geri verdiğinde, sistem onActivityResult() metodunu çağırır. Bu metod içinde 3 argüman bulunur:

  • startActivityForResult() metoduna geçirilen talep kodu.
  • Çağrılan aktivite tarafından tanımlanan sonuç kodu (Eğer işlem başarılı ise RESULT_OK, kullanıcı işlemi iptal ederse veya işlem başarısız olursa RESULT_CANCELED değerini alır).
  • Sonuç verisini taşıyan intent.

pickContact() metodu içinde kullanılan intent sonucunda aşağıdaki metod kullanılır:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // İşlem yaptığımız talebi belirleme
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Sonuç kodunun başarılı olduğunu kontrol etme
        if (resultCode == RESULT_OK) {
            // Kullanıcı bir kişi seçmiş durumdadır.
            // Intent verisindeki Uri değeri hangi kişinin seçildiğini belirler.

            // Seçilen kişiyi gösteren URI değerini elde etme
            Uri contactUri = data.getData();
            // Sonuçta tek satır değer olduğundan, sadece NUMBER sütununa ihtiyaç vardır.
            String[] projection = {Phone.NUMBER};

            // NUMBER sütununu elde etmek için kişi sorgulama
            Cursor cursor = getContentResolver().query(contactUri, projection, null, null, null);
            cursor.moveToFirst();

            // NUMBER sütunundan telefon numarası elde etme
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);

            // Telefon numarası ile işlem yapma			
        }
    }
}

Diğer uygulamaların kendi aktivitenizi kullanması

Diğer uygulamaların sizin aktivitenizi çalıştırabilmesi için; AndroidManifest.xml dosyasındaki <activity> elemanı içine bir <intent-filter> elemanı eklemeniz gerekir.

Uygulamanız bir cihaza yüklendiğinde, sistem intent filtrelerini belirler ve gerekli bilgileri yüklenen tüm uygulamalar tarafından desteklenen dahili bir intent kataloğuna ekler. Bir uygulama dolaylı intent kullanarak startActivity() veya startActivityForResult() metodunu çağırdığında, sistem intent için gerekli işlemi yapacak aktiviteleri bulur.

Programınızda yer alan bir aktivitenin hangi intent'lere işlem yapabileceğini uygun bir şekilde tanımlamak için, her bir intent filtresi işlemin türü ve veri açısından belirgin olacak şekilde eklenmelidir.

Eğer başlatılacak olan aktivite intent nesnesinin aşağıdaki kriterlerini yerine getirebilecek bir intent filtresine sahipse, sistem bir intent'i işlem yapılmak üzere bir aktiviteye gönderebilir:

Action

Uygulanacak işlemin adını gösteren bir karakter dizisidir. Genellikle, ACTION_SEND veya ACTION_VIEW gibi bir değer alır.

Bu değer intent filtresi içinde <action> elemanı ile birlikte tanımlanır.

Data

Intent ile ilgili verinin açıklamasıdır.

Bu değer intent filtresi içinde <data> elemanı ile birlikte tanımlanır.

Category

Intent ile ilgili verinin açıklamasıdır.

Intent'e işlem yapan aktiviteyi belirlemek için ek bir yol sağlar. Sistem tarafından desteklenen bir kaç farklı kategori bulunmasına rağmen pek sık kullanılmaz. Tüm dolaylı intent'ler CATEGORY_DEFAULT değeri ile tanımlanır.

Bu değer intent filtresi içinde <category> elemanı ile birlikte tanımlanır.

Aşağıda veri türü metin veya resim olduğunda ACTION_SEND intent'ine işlem yapan bir intent filtresine sahip bir aktvite bildirimi yer almaktadır:

For example, here's an activity with an intent filter that handles the ACTION_SEND intent when the data type is either text or an image:
<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    </intent-filter>
</activity>

Gelen her bir intent sadece tek bir action ve data türü içerir. Ancak, her bir <intent-filter> içinde birden fazla <action>, <category> ve <data> elemanı tanımlayabilirsiniz.

Eğer herhangi çift action ve data ikilisi birbiri ile uyuşmuyorsa, ayrı ayrı intent filtreleri tanımlayarak birbiri ile uyuşan action ve data eşleştirmesi yapmanız gerekir.

Aktiviteniz hem metin hem de resim verileri için ACTION_SEND ve ACTION_SENDTO intent'lerinin her ikisi ile işlem yaptığında, iki action için ayrı ayrı iki ayrı intent filtresi tanımlamnız gerekir. Çünkü; ACTION_SENDTO intent'inin, send veya sendto URI scheme'i kullanarak alıcı adresini tanımlamak için, Uri verisini kullanması gerekir:

<activity android:name="ShareActivity">
    // Metin verisi göndermek için filtre, SENDTO action değerini sms URI scheme ile kabul eder.
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    </intent-filter>
    // Metin ve resim verisi göndermek için filtre, SEND action ile metin ve resim verisi kabul eder.
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
</activity>

Dolaylı intent'leri almak için, intent filtre category elemanında CATEGORY_DEFAULT değerini kullanmanız gerekir. startActivity() ve startActivityForResult() metodları tüm intent'lere CATEGORY_DEFAULT category içinde yer alıyor gibi işlem yapar. Eğer onun bildirimini yapmazsanız, hiç bir dolaylı intent aktiviteniz içinde işlem görmez.

Aktiviteniz içinde yapılacak işlemi belirlemek için aktivitenizi başlatan intent'i okutabilirsiniz.

Aktiviteniz başlatıldığında, getIntent() metodunu kullanarak aktivitenizi başlatan intent'i elde edebilirsiniz. Bu işlemi aktivitenizin çalışmaya devam ettiği süre içinde herhangi bir zamanda yapabilirsiniz, ancak onCreate() veya onStart() metodları içinde yapmanız tavsiye edilir.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    // Aktiviteyi başlatan intent'i elde etme
    Intent intent = getIntent();
    Uri data = intent.getData();

    // intent türüne bağlı olarak yapılacak işlemi belirleme
    if (intent.getType().indexOf("image/") != -1) {
        // Resim verisi içeren intent'lere işlem yapar ...
    } 
	else if (intent.getType().equals("text/plain")) {
        // Metin verisi içeren intent'lere işlem yapar ...
    }
}

Aktivitenizi başlatan aktiviteye bir sonuç döndürmek isterseniz, setResult() metodunu kullanarak sonuç kodunu ve sonuç intent'ini tanımlayabilirsiniz. İşleminiz sona erdiğinde ve kullanıcı çağıran aktiviteye döndüğünde, finish() metodunu kullanarak aktivitenizi kapatabilirsiniz:

// Sonuç verilerini göndermek için intent oluşturma
Intent result = new Intent("com.example.RESULT_ACTION",Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();

Sonuç ile birlikte daima bir sonuç kodu tanımlamanız gerekir. Bu kod genellikle RESULT_OK veya RESULT_CANCELED değeri alır. Bunun dışında, eğer gerek duyulursa, intent ile ek bilgi tanımlayabilirsiniz.

Sonuç kodu ön tanımlı olarak RESULT_CANCELED değeri alır. Böylece, eğer kullanıcı işlem tamamlanmadan ve siz sonuç değerini belirlemeden Geri butonuna basarsa, çağıran aktivite "iptal edildi" sonucunu alır.

Sonuç seçeneklerinden bir tanesini gösteren bir integer değer geri döndürmek isterseniz, sonuç koduna sıfırdan daha yüksek olan herhangi bir değer verebilirsiniz. Eğer sonuç kodunu bir integer döndürmek ve intent'i içerecek şekilde kullanmak isterseniz, setResult() metodunu sadece sonuç kodu ile kullanabilirsiniz.

setResult(RESULT_COLOR_RED);
finish();