Hi guys.
Today i am going to show you a finish product of my transparent flaslight application that shows the battery status. This application is made by using ChatHeads (Overlay) method which is also used by Facebook Messenger.
1. Overlay Window İleFlashLight
Merhaba arkadaşlar. Sizlere facebook messenger da kullanılan Overlay Window(ChatHeads) metoduyla bataryanın durumunu da gösteren transparan el feneri uygulamasının bitmiş halini göstereceğim.
Bugün hep beraber Facebook ile popüler olmuş ve yavaş yavaş YouTube, Pocket ve son olarak Skype tarafından kullanılmaya başlanan "overlay drawing" tekniğini kendi uygulamamız için nasıl kullanabileceğimize bir bakalım.
Aslında overlay drawing tekniğini Android'in Window Manager'ını kullanarak sanal bir "çok görevlilik" (multitasking) ortamı oluşturma ve birden çok uygulama arasında geçişi kolaylaştıran farklı bir uygulama geliştirme yaklaşımı olarak açıklayabiliriz.
2. Proje Oluşturma Ve Kodlama Kısmına Giriş
File-New-Androd Application
Project Seçiyoruz
3. Projemiz için bir ad belirliyoruz.İsterseniz bu projenin çalışacağı
Android sürüm aralığını seçebilirsiniz.
7. MainActivity.java
package com.example.overlyflashlight;
//Yeni proje oluştururken uygulamaya verdiğimiz isim olarak paket ismi atadı
//paket ismi eşşiz olmalıdır.Bu yüzden geliştiriciler genellikle paket isimlerini web sitelerine ait url lerini koyar. Örn: com.stackcuriosity.UygulamaIsmi
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
İmport ifadesi ile bize gerekli olan kütüphane dosyalarını getirir
8. MainActivity.java
public class MainActivity extends Activity {
//Class ismimiz ve extends ( Kısaca bir sınıfın başka bir sınıftaki methodlara //ve değişkenlere sahip olabilmesi için yapılan işlemdir.) ettiğimiz Activity //class ımız.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent overlayIntent = new Intent();
overlayIntent.setClass(this, OverlayService.class);
this.startService(overlayIntent);
finish();
}
Bu class’ımzı asıl işlemi Yaptığımız OverlayService Class ımızı tetiklemesi için Kullanacağız.Bu yüzden Burada ir intent tanımladık ve service class’ımızı bu main- activity class’a atadık sonrada finish() metoduyla kapattık.
10. OverlayService.java
Bu class’ımız asıl işlemin overlay tekniğini kullandığımız class’ımız.
Aslında overlay drawing tekniğini Android'in Window Manager'ını kullanarak sanal bir "çok görevlilik" (multitasking) ortamı oluşturma ve birden çok uygulama arasında geçişi kolaylaştıran farklı bir uygulama geliştirme yaklaşımı olarak açıklayabiliriz.
Bizim bu iş için başvuracağımız tüyo, öncelikle Android tarafında SYSTEM_ALERT_WINDOW yetkisini alarak normal Window üzerine yarı geçirgen-transparan herhangi bir View'ı çizmeye ve yerleştirmeye dayanıyor. View, overlay (kaplama) olarak konulduğundan dolayı, kilit ekranı hariç bütün uygulamalarımızın üzerine kendini konumlandırabiliyor. Bu işlemi gerçekleştirebilmek için
13. OverlayService.java
Bu servis bize aşağıdaki metotlarla View'ları yönetme olanağı sunuyor:
addView()
removeView()
updateViewLayout()
14. OverlayService.java
Ayrıca kullanacağımız View'ı XML dosyasından okuyacağımızdan bir LayoutInflater sınıfına ihtiyacımız var. Bunu LayoutInflater.from(this) ile (OverlayService:59) servis üzerinden doğrudan yaratabiliyoruz.
Daha sonra layoutInflater.inflate(R.layout.activity_main, null) çağrısıyla View'ımızı XML'den deserialize edip yaratıyoruz ve artık WindowManager ile kullanıma hazır halde.
Daha sonra WindowManager.addView() ile deserialize ettiğimiz View'ımızı doğrudan ekranımıza ekliyoruz.
15. OverlayService.java
Daha sonra WindowManager.addView() ile deserialize ettiğimiz View'ımızı doğrudan ekranımıza ekliyoruz.
layoutView=inflater.inflate(R.layout.activity_main,null);
windowsManager.addView(layoutView,params);
16. OverlayService.java
Burada WindowManager'a yeni View'ımızı eklerken aşağıdaki parametreleri kullanıyoruz
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PRIORITY_PHONE,
LayoutParamFlags,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
17. OverlayService.java
Yukarıdaki bu parametreler eklediğimiz View'ın ilk olarak ekranın sol üst köşesinde çıkmasını, içine koyduğumuz View'ı olduğu gibi sarmasını, standart olarak kullanılan halinin yarı-geçirgen (yarı şeffaf) olmasını, ayrıca Window tipinin Priority Phone olarak ayarlanmış olmasını sağlıyor.
Projede ben iki tane listener register ettim: Birincisi OnClickListener, ikincisi OnTouchListener.
OnTouchListener sayesinde, kullanıcının oluşturmuş olduğumuz ikonu ekran üzerinde sürükleyip bırakması için gerekli işlemleri yapıyoruz. OnClickListener sayesinde de kullanıcının ikonu tıklaması sonucunda flaş ışığının açılmasını sağlıyoruz.
18. OverlayService.java: Kaynak Kodları
public class OverlayService extends Service{
private static final int LayoutParamFlags = WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
19. OverlayService.java: Kaynak Kodları
private LayoutInflater inflater;
private Display mDisplay;
private View layoutView;
private WindowManager windowManager;
private WindowManager.LayoutParams params;
private View.OnTouchListener touchListener;
private View.OnClickListener clickListener;
int key=0;//1-buton on-off özelliği için
private TextView batteryPercent;//batarya durumu %
static int level ;//bataryanın doluluk oranı
private ProgressBar pbar; // progressbar tanımladık
//Flash için camera ayarları
private boolean flashVarMi;
private boolean flashAcikMi;
private Camera camera;
Parameters paramsCam;
22. OverlayService.java: Kaynak Kodları
//Şimdi burada hem transparan hemde slidingDrawer olarak bildiğimiz açılır kapanır bir Transparent.java class ımızda tanımladığımız özel bir layout tanımladık.
DrawerLayout nedir ? Ana activity` yi oluşturduğumuzda Layout olarak bununla eşleştireceğiz. Bu bizim soldan gelen menunun oluşması için android` in sağlamış olduğu bi düzen.Aslında bizim burada yaptığımız custom(özelleştirdimiz)drawer layouttur.
final Transparent popup = (Transparent) layoutView.findViewById(R.id.popup_window);
popup.setVisibility(View.GONE);
final ImageButton button = (ImageButton) layoutView.findViewById(R.id.toggle);
getCam(); //burası flash açmak için telefonun kamerasına bağlandığımız yer.
23. OverlayService.java: Kaynak Kodları
clickListener = new OnClickListener() { //yukarda bahsettik.
@Override
public void onClick(View view) {
try {
if(key==0){ //burada key dediğimiz aslında butona basıldığında ne yapılacağı eyer key sıfır ise flaş açıktır.
key=1; //key sıfır yaptıktan sonra bu metot’a giriliecek ve bu metottaki kodlarımız çalışcak birdaha butona bastığında kapanması için key’e bir değerini atıyoruz
try {
popup.setVisibility(View.VISIBLE); //slidingDrawer, buton tıklandğında açılması için
view.setBackgroundResource(R.drawable.flashon); //butonun şeklini değiştiriyoruz
if(camera==null){
getCam(); //Burası çok önemli* eyer bu metot’u belirtmezsek ilerde göstericem flash ı tamamen kapattığımızda(release ettiğimizde) tekrar açmaya çalıştığımızda çalışmaz
}
24. OverlayService.java: Kaynak Kodları
yukarı slaytın devamı;
getBatteryPercentage(); // oluşturdumuz batarya durumunu okumak için metodu burada kullandık.
flashAc(); //flashı açmak için gerekli kodları tanımladığımız metot.
} catch (Exception e) {
//Olası bir hata durumunda hata buraya düşer sizde buradan alıp logcat vs. araçlarla hatayı görebilirsiniz
}
}
25. OverlayService.java: Kaynak Kodları
else if(key==1){ //key’i bir yapmıştık bu durumda butona tıklanması halinde bu kod bloğu //çalışacaktır ve flashKapanacaktır.
key=0; //bu kod bloğu çalıştığında tekrar 0 yapıyoruz ki butona bidaha tıklarsa flash açılsın die
try {
popup.setVisibility(View.GONE); //slidingDrawer butona tıklanıp flash kapandığında kapanması için.
flashKapa(); //flash’ı kapattığımız metot
if (camera != null) {
/*dediğimiz önemli metot* arkadaşlar bunu önemli cılan uygulamamız overlay Windows şeklinde tanımladık yani sürekli ekranda açıkkalacak şekilde böyle olunca flash her zaman açık kalmıyacak eyer biz bu metot ‘u tanımlamazsak flash açık olmasa bile kamerayı kullanmaya devam edecektir.Bu durum da başka bir camerayı kullanan bir uygulama açmaya çalıştığınızda kamerayı kullanamamanıza ve hata almanıza sebeb olacaktır.*/
31. OverlayService.java: Kaynak Kodları
Bu kod bloğu natifacation bar’a yerleştireceğimiz ve Window Service’i kapatmamıza yarayacak bir nevi kapat butonu görevi görecek bir sekme.
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getBooleanExtra("stop_service", false)){
// If it's a call from the notification, stop the service.
stopSelf();
}else{
// Make the service run in foreground so that the system does not shut it down.
Intent notificationIntent = new Intent(this, OverlayService.class);
notificationIntent.putExtra("stop_service", true);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, notificationIntent, 0);
32. OverlayService.java: Kaynak Kodları
Notification notification = new Notification(
R.drawable.flashactionbar, //natification bara icon atadık
"FlashLight Launch", // uygulama ilk başladığında gösterilecek
System.currentTimeMillis());
notification.setLatestEventInfo(
this,
"FlashLight Başatıldı", //natifacation barı açtığınızda gözükecek başlık
"FlashLight Kapatmak İçin Dokun.", //kullanıcıya gösterdimiz mesaj
pendingIntent);
startForeground(86, notification);
}
return START_STICKY;
}
41. Transparent.java: Kaynak Kodları
Bu metotda custom olarak oluşturduğumuz slidingDrawer in sınırlarını çizdik
private void init() {
innerPaint = new Paint();
innerPaint.setARGB(50, 0, 0, 50); //arka planı şeffaf yapmak için yaptm
innerPaint.setAntiAlias(true);
borderPaint = new Paint();
borderPaint.setARGB(0, 0, 0, 0); //arka planı şeffaf yapmak için yaptm
borderPaint.setAntiAlias(true);
borderPaint.setStyle(Style.STROKE);
}
42. Transparent.java: Kaynak Kodları
public void setInnerPaint(Paint innerPaint) {
this.innerPaint = innerPaint;
}
public void setBorderPaint(Paint borderPaint) {
this.borderPaint = borderPaint;
}
En başta tanımladığımız private Paint innerPaint, borderPaint ‘in Sağ click-source-Generate getter and Setter dan setter ları oluşturduk
43. Transparent.java: Kaynak Kodları
@Override
protected void dispatchDraw(Canvas canvas) {
RectF drawRect = new RectF();
drawRect.set(0,0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(drawRect, 5, 5, innerPaint);
canvas.drawRoundRect(drawRect, 5, 5, borderPaint);
super.dispatchDraw(canvas);
}
}
Son olarak da ekrana çizdik.
54. Res-Layout: activity_main.xml
<ImageButton
android:id="@+id/toggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@+id/popup_window"
android:layout_toRightOf="@+id/popup_window"
android:background="@drawable/flashoff"
android:clickable="true" />
</RelativeLayout>
Tanımladğımız bu buton
slidingDrawerde Handle
butonuna karşılık gelir.
Aynı zamanda biz bu buton-
u overlay Window Olarak
oluşturduğumuz uygulamız’
ın resmi(facebookdaki soh-
bet balonlarına) olarak
kullandık.