본문 바로가기

안드로이드 개발/Service

Notification에서 앱 실행 with Service

반응형
안드로이드 노티피케이션에서 앱 바로가기를 만들어 보자. 

노티피케이션이 없어지지 않기 위해 서비스를 사용한다.


핵심은 서비스로 Notification을 Foreground로 실행 한다. 

그리고 View에서 버튼을 누르면 해당 패키지명을 intent로 날린다. 

이 intent를 받은 브로드케스트를 등록하여 앱을 실행 하도록 처리 하면 된다.


예제 코드 다운로드-

Qinker.zip



SVN-

svn checkout --username anonsvn https://dev.naver.com/svn/linker

The password is 'anonsvn'



Service 구현 내용 

package com.kmshack.qinker.service;


import java.lang.reflect.Method;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.RemoteViews;

import com.kmshack.qinker.MainActivity;
import com.kmshack.qinker.R;
import com.kmshack.qinker.utils.GraphicUtils;

public class QinkerService extends Service {
	public static final String UPDATE = "com.kmshack.qinker.service.update";
	public static final String CMD = "com.kmshack.qinker.service.cmd";
	
    public static final int SERVICE_STATUS = 1;
    
    private Notification mNotification;
    
	private final IQinkerService.Stub mBinder = new IQinkerService.Stub() {
		
		@Override
		public boolean stopService() throws RemoteException {
			return false;
		}
		
		@Override
		public boolean startService() throws RemoteException {
			return false;
		}
		
		@Override
		public boolean isStart() throws RemoteException {
			return false;
		}
	};

	@Override
	public IBinder onBind(Intent arg0) {
		return mBinder;
	}
	
	@Override
	public void onCreate() {
		super.onCreate();
		
        IntentFilter commandFilter = new IntentFilter();
        commandFilter.addAction(UPDATE);
        commandFilter.addAction(CMD);
        registerReceiver(mIntentReceiver, commandFilter);
        
        showNotification();
	}
	
    private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    	
        @Override
        public void onReceive(Context context, Intent intent) {
        	handleCommand(intent);
        }
    };
    
    private void handleCommand(Intent intent){

    	if (intent != null) {
        	String action = intent.getAction();
        	
        	if(action == null)
        		return;
        	
        	if(action.equals(CMD)){
        		String packageName = intent.getStringExtra("package_name");
        		startActivityForPackageName(packageName);
        	}
    	}
    }
    
    /**
     * 앱을 실행한다.
     * @param packageName
     */
    private void startActivityForPackageName(String packageName){
    	disableStatusBar();
    	
    	PackageManager pm = getPackageManager();
		Intent app = pm.getLaunchIntentForPackage(packageName);
		
		this.startActivity(app);
    }
    
    /**
     *  상태바를 올린다.
     */
    private void disableStatusBar(){
    	try{
	        Object service  = getSystemService("statusbar");
	        Class statusbarManager = Class.forName("android.app.StatusBarManager");
	        
	        Method collapse = null;
	        
	        if (Build.VERSION.SDK_INT  < 17) {
	        	collapse = statusbarManager.getMethod("collapse");
	        } else {
	        	collapse = statusbarManager.getMethod("collapsePanels");
	        }
	        collapse.setAccessible(true);
	        collapse.invoke(service);
        }catch(Exception ex){
        }
    }
    
    /**
     * 노티피케이션을 표시한다.
     */
    private void showNotification(){
    	Intent contentsIntent = new Intent(getApplicationContext(), MainActivity.class);
    	
    	 mNotification =  new Notification.Builder(getApplicationContext())
								         .setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, contentsIntent, 0))
								         .setSmallIcon(R.drawable.ic_launcher)
								         .setAutoCancel(false).getNotification();
    	 
    	 RemoteViews views = new RemoteViews(this.getPackageName(), com.kmshack.qinker.R.layout.notification);

    	 Intent intent = new Intent(CMD);
    	 intent.setComponent(new ComponentName(getApplicationContext(), QinkerService.class));
    	 intent.putExtra("package_name", "com.kmshack.BusanBus");
    	 
    	 PendingIntent contentIntent = PendingIntent.getService(getApplicationContext(), 0, intent, 0);
    	 views.setOnClickPendingIntent(R.id.button1, contentIntent);
    	 
    	 views.setImageViewBitmap(R.id.button1, getAppIconResource("com.kmshack.BusanBus"));
    	 
    	 mNotification.contentView = views;
		 mNotification.flags |= Notification.FLAG_ONGOING_EVENT;
	
		startForeground(SERVICE_STATUS, mNotification);
    }
	
    private Bitmap getAppIconResource(String packageName){
    	PackageManager pm = getPackageManager();
		try {
			Drawable icon =  pm.getApplicationIcon(packageName);
			return GraphicUtils.getBitmapForDrawable(icon);
		} catch (NameNotFoundException e) {
		}
		return null;
    }
    
	@Override
	public void onDestroy() {
		stopForeground(true);
		unregisterReceiver(mIntentReceiver);
		super.onDestroy();
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		handleCommand(intent);
		return super.onStartCommand(intent, flags, startId);
	}

	@Override
	public boolean onUnbind(Intent intent) {
		return super.onUnbind(intent);
	}

}




반응형

'안드로이드 개발 > Service' 카테고리의 다른 글

Start Service at Boot Time  (0) 2010.08.18