【Android】Binder Service + interface + 非同期(Callback)

# 1. interface(サービス側、クライアント側両方)
```BinderCallback.aidi
package service;

interface BinderCallback
{
	oneway void getNumCallback( int Num );
}
```

```BinderInterface.aidi
package service;

import service.BinderCallback;

interface BinderInterface
{
	oneway void getNum( BinderCallback );
}
```
# 2. Service クラス
サービス側のActivityの説明は省略する。

```Service.java
package service;

public class Service extends Service
{
    private int     mCurNum      = 0;
    private Thread  mCountThread = null; 

    @Override
    public void onCreate()
    {
        super.onCreate();
        
        // 1. Notification
        // ====================================================================
        Intent intent = new Intent(this, MainActivity.class );
        PendingIntent pIntent = PendingIntent.getActivity( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
                                   
        Notification noti = new NotificationCompat.Builder(this)
                    .setContentTitle("Count Service")
                    .setContentText("Running Count Service")
                    .setSmallIcon( R.drawable.ic_launcher )
                    .setContentIntent( pIntent )
                    .build();
        // ==================================================================== 
        
        // 2. foregroud setting
        // ====================================================================
        startForeground( 1234, noti );
        // ====================================================================
    }

    @Override
    public int onStartCommand( Intent intent, int flags, int startId )
    {
        super.onStartCommand( intent, flags, startId );
        
        if( mCountThread == null)
        {
            mCountThread = new Thread("Count Thread")
            {
                public void run()
                {
                    while( true )
                    {                       
                        mCurNum ++;
                        
                        try{ Thread.sleep( 1000 ); }
                        catch( InterruptedException e ) 
                        {
                            break;
                        };
                    }
                }
            };
            
            mCountThread.start();
        }
        
        return START_REDELIVER_INTENT; 
    }

    @Override
    public void onDestroy()
    {       
        stopForeground( true );
        
        if( mCountThread != null )
        {
            mCountThread.interrupt();
            mCountThread = null;
            mCurNum = 0;
        }
        super.onDestroy();
    }

    // Binder 非同期 + Callback 関数利用
    BinderInterface.Stub mBinder = new BinderInterface.Stub() 
    {
		
		@Override
		public void getNum(BinderCallback callback) throws RemoteException {
			
			// Bind Service 遅延誘導
			try 
			{
				Thread.sleep(10000);
			} 
			catch (InterruptedException e) 
			{
				e.printStackTrace();
			}
			
			callback.getNumCallback(mCurNum);
		}
	};
	
    @Override
    public IBinder onBind( Intent intent )
    {
        // クライアントに Binder リターン
        return mBinder;
    }
    
    @Override
    public boolean onUnbind( Intent intent )
    {
        return super.onUnbind( intent );
    }
}
```
# Client Activity
```MainActivity.java
public class MainActivity extends Activity
{
   
	private BinderInterface mBinder = null;
	
	// Callback 関数実装
	BinderCallback mCurCountCallback = new BinderCallback.Stub() 
	{

		@Override
		public void getNumCallback(final int Num) throws RemoteException 
		{
			runOnUiThread(new Runnable()
			{

				@Override
				public void run() 
				{
					Toast.makeText(MainActivity.this, "Cur Count : " + Num, Toast.LENGTH_LONG).show();
				}
				
			});
			
		}
	};
	
    private ServiceConnection mConnection = new ServiceConnection()
    {
        @Override
        public void onServiceConnected( ComponentName name, IBinder service )
        {
            mBinder = BinderInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected( ComponentName name )
        {
        }
    };
    
    @Override
    protected void onCreate( Bundle savedInstanceState )
    {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );
        
        // サービス接続
        // ====================================================================
        Intent serviceIntent = new Intent("service.Service");
        bindService( serviceIntent, mConnection, BIND_AUTO_CREATE );
        // ====================================================================
    }
    
    @Override
    protected void onDestroy()
    {
        // サービス解除
        // ====================================================================
        unbindService( mConnection );
        // ====================================================================
        
        super.onDestroy();
    }


    public void onClick( View v )
    {
        switch( v.getId() )
        {
            // 1. サービス開始
            // ================================================================
            case R.id.start_count_btn:
            {
                Intent serviceIntent = new Intent("service.Service");
                startService( serviceIntent );

                break;
            }
            // ================================================================
            
            // 2. サービス終了
            // ================================================================
            case R.id.stop_count_btn:
            {
                Intent serviceIntent = new Intent("service.Service");
                stopService( serviceIntent );
                break;
            }
            // ================================================================
            
            // 3. 現在のカウント表示
            // ================================================================
            case R.id.get_cur_count_number_btn:
            {            	
            	try 
            	{            		
            		mBinder.getNum(mCurCountCallback);
				} 
            	catch (RemoteException e) 
            	{	
					e.printStackTrace();
				}
            	
                break;
            }
            // ================================================================
        }
    }
}

```