2013年10月6日日曜日

IntentService を使ってみる:android

http://developer.android.com/guide/components/services.html で紹介されているソースコードを実行してみる。
サービスの終了操作を気にしないでいいようです。
5秒後にサービス終了するコード。

package com.example.intentservice;

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

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  Intent intent = new Intent(this, HelloIntentService.class);
  startService(intent);
 }
}

package com.example.intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";

 /** 
  * A constructor is required, and must call the super IntentService(String)
  * constructor with a name for the worker thread.
  */
 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");
 }

 /**
  * The IntentService calls this method from the default worker thread with
  * the intent that started the service. When this method returns, IntentService
  * stops the service, as appropriate.
  */
 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  // Normally we would do some work here, like download a file.
  // For our sample, we just sleep for 5 seconds.
  long endTime = System.currentTimeMillis() + 5 * 1000;
  while (System.currentTimeMillis() < endTime) {
   synchronized (this) {
    try {
     wait(endTime - System.currentTimeMillis());
    } catch (Exception e) {
    }
   }
  }
  Log.v(TAG, "onHandleIntent 終了");
 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
 }

}


UIの変更を考えてみる
package com.example.intentservice;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.widget.TextView;

public class MainActivity extends Activity {

 public static class SampleHandler extends Handler {
  private MainActivity con;

  public SampleHandler(MainActivity mainActivity) {
   // TODO 自動生成されたコンストラクター・スタブ
   this.con = mainActivity;
  }

  @Override
  public void handleMessage(Message msg) {
   Bundle bundle = msg.getData();
   
    TextView textView = (TextView) con.findViewById(R.id.textView1);
    textView.setText( bundle.getString("mystring") );
  }
 }

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  
  SampleHandler handler = new SampleHandler(this);

  Intent intent = new Intent(this, HelloIntentService.class);
  intent.putExtra("messenger", new Messenger(handler));
  startService(intent);
 }
}

package com.example.intentservice;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";

 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");
 }

 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  Bundle bundle = intent.getExtras();
  if (bundle != null) {
   Messenger messenger = (Messenger) bundle.get("messenger");
   Message msg = Message.obtain();
   
   Bundle data = new Bundle();
   data.putString("mystring", "Hello!");
   msg.setData(data);
   try {
    messenger.send(msg);
   } catch (RemoteException e) {
    Log.i("error", "error");
   }
  }
 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
 }

}

while ループが永遠に終わらない処理の場合、
呼び出し元のアクティビティーが終了しても、動き続けるので、
IntentServiceを終了させる処理が必要なようです。


package com.example.intentservice;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.widget.TextView;

public class MainActivity extends Activity {

 public static class SampleHandler extends Handler {
  private MainActivity con;

  public SampleHandler(MainActivity mainActivity) {
   // TODO 自動生成されたコンストラクター・スタブ
   this.con = mainActivity;
  }

  @Override
  public void handleMessage(Message msg) {
   Bundle bundle = msg.getData();

   TextView textView = (TextView) con.findViewById(R.id.textView1);
   textView.setText(bundle.getString("mystring"));
  }
 }

 private SampleHandler handler;
 private Intent intent;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  handler = new SampleHandler(this);

  intent = new Intent(this, HelloIntentService.class);
  intent.putExtra("messenger", new Messenger(handler));
  startService(intent);
 }

 @Override
 public void onDestroy() {
  super.onDestroy();
  // The service is no longer used and is being destroyed

  if (intent != null) {
   stopService(intent);
   intent = null;
  }
 }
}
package com.example.intentservice;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class HelloIntentService extends IntentService {

 private static final String TAG = "HelloIntentService";
 private boolean loopFlag = true;

 public HelloIntentService() {
  super("HelloIntentService");

  Log.v(TAG, "HelloIntentService");

 }

 @Override
 protected void onHandleIntent(Intent intent) {
  Log.v(TAG, "onHandleIntent");

  Bundle bundle = intent.getExtras();

  while (loopFlag) {
   synchronized (this) {
    try {
     Log.v(TAG, "HelloIntentService");
     GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
     String stringTime = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

     if (bundle != null) {
      Messenger messenger = (Messenger) bundle.get("messenger");
      Message msg = Message.obtain();

      Bundle data = new Bundle();

      data.putString("mystring", stringTime);
      msg.setData(data);
      try {
       messenger.send(msg);
      } catch (RemoteException e) {
       Log.i("error", "error");
      }
     }

     wait(1000);
    } catch (Exception e) {
    }
   }
  }

 }

 @Override
 public void onDestroy() {
  Log.v(TAG, "onDestroy");
  loopFlag = false;
 }

}

2013年10月5日土曜日

Service と BroadcastReceiver :android



Activity で レシーバーを登録して、インテントでサービスを開始する。

サービスでは、システムの時間を取得して、レシーバーに送る。

レシーバーでは受っとった時間を画面に表示する。

package com.example.servicetest;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {
 IntentFilter intentFilter;
 MyService4Receiver receiver;
 Intent intent = null;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  // レシーバーの登録
  receiver = new MyService4Receiver();
  receiver.activity = this;
  intentFilter = new IntentFilter();
  intentFilter.addAction(MyService4Service.actionName);
  registerReceiver(receiver, intentFilter);
 }
 
 public void onResume() {
  super.onResume();
  Log.i("タグ", "onResume()");

  intent = new Intent(getBaseContext(), MyService4Service.class);
  startService(intent);
 }
 
 public void onDestroy() {
  super.onDestroy();
  Log.i("タグ", "onDestroy()");
  
  unregisterReceiver(receiver);//レシーバー登録解除
  
  if (intent != null)
  {
   stopService(intent);//サービスの停止
  }
  intent = null;

 }

}

package com.example.servicetest;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class MyService4Service extends Service {
 public static final String actionName = "MYSERVICE4_ACTION";
 MyHandler mHandler = null;
 private static Context contex;

 @Override
 public int onStartCommand(Intent intent, int flags, int startId) {
  Log.i("MyService4Service", "onStartCommand");

  if (mHandler == null)
  {
   mHandler = new MyHandler();
   mHandler.sendEmptyMessage(1);
  }
  
  contex = getBaseContext();

  return START_NOT_STICKY;//サービスの強制終了後、再起動しない
 }

 public void onDestroy()
 {
  if (mHandler != null)
  {
   mHandler.removeMessages(1);
   mHandler = null;
  }
  super.onDestroy();
 }

 @Override
 public IBinder onBind(Intent arg0) {
  // TODO 自動生成されたメソッド・スタブ
  return null;
 }

 static class MyHandler extends Handler
 {
  public void handleMessage(Message msg)
  {
   GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
   String stringTime = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

   Intent broadcastIntent = new Intent();
   broadcastIntent.putExtra("message", stringTime);
   broadcastIntent.setAction(actionName);
   contex.sendBroadcast(broadcastIntent);

   sendEmptyMessageDelayed(1, 1000);
  }
 }
}
package com.example.servicetest;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class MyService4Receiver extends BroadcastReceiver {
 MainActivity activity;// onCreate の receiver.activity = this;


 @Override
 public void onReceive(Context context, Intent intent) {
  // メッセージを取ってくる
  
  Log.i("MyService4Receiver", "onReceive");
  
  Bundle bundle = intent.getExtras();
  String message = bundle.getString("message");
  // そいつを表示する
  if (activity != null)
  {
   TextView tv = (TextView) activity.findViewById(R.id.textView1);
   tv.setText(message);
  }
 }
}

サービスはマニフェストにも登録しておく、
レシーバはregisterReceiver();で動的に登録してあるので、マニフェストには登録しなくても動く。

2013年10月4日金曜日

サービスのバインドについて考えてみる


サービスをバインドして、サービスからUIを変更
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  tv = (TextView) findViewById(R.id.textView1);

 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   LocalBinder binder = (SampleService.LocalBinder) service;
   binder.getService(tv);
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {
        SampleService getService(TextView tv) {
      Log.i(TAB, "LocalBinder");//
      tv.setText("サービスから変更");
            return SampleService.this;
        }
    }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }
}

ボタンクリックでUIを変更してみる
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  tv = (TextView) findViewById(R.id.textView1);

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null){
     Log.i(TAB, "binder は null で無い");
     binder.getService(tv);
    }else{
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {
  void getService(TextView tv) {
   Log.i(TAB, "LocalBinder");//
   tv.setText("サービスから変更");
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }
}


サービスでスレッドを利用して定期的にUIを更新
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  tv = (TextView) findViewById(R.id.textView1);

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null){
     Log.i(TAB, "binder は null ではない");
     binder.getService(tv);
    }else{
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;

public class SampleService extends Service {

 private Handler handler;

 public class MyThread implements Runnable {

  private int data;

  @Override
  public void run() {
   // TODO 自動生成されたメソッド・スタブ
   while (true) {
    Log.i(TAB, "run::" + data);//二番目に呼ばれる

    data++;
    Message msg = handler.obtainMessage();
    msg.arg1 = data;
    handler.sendMessage(msg);
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     // TODO 自動生成された catch ブロック
     e.printStackTrace();
    }
   }
  }

 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(final TextView tv) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   new Thread(new MyThread()).start();

   /*
   //動くがメモリーリークの可能性がある
   //This Handler class should be static or leaks might occur
   handler = new Handler() {
    public void handleMessage(Message msg) {
     //updata.update(tv, data);
     Log.i(TAB, "handleMessage::" + msg);

     tv.setText(String.valueOf(msg.arg1));//ここでも変更可能

    }
   };
   */
   handler = new MyHandler(tv);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private TextView tv;

  public MyHandler(TextView tv) {
   // TODO 自動生成されたコンストラクター・スタブ
   this.tv = tv;
  }

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);
   tv.setText(String.valueOf(msg.arg1));//ここでも変更可能
  }

 }
}

サービスで変更された値をアクティビティに戻してUIを変更する。
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;
import com.example.bindservice.SampleService.UpdateData;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  tv = (TextView) findViewById(R.id.textView1);

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null) {
     Log.i(TAB, "binder は null ではない");
     binder.getService(new UpdateData() {

      @Override
      public void update(int data) {
       // TODO 自動生成されたメソッド・スタブ
       tv.setText(data + "");
      }
     });

    } else {
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SampleService extends Service {

 public interface UpdateData {
  public void update(int data);
 }

 private Handler handler;

 public class MyThread implements Runnable {

  private int data;

  @Override
  public void run() {
   // TODO 自動生成されたメソッド・スタブ
   while (true) {
    Log.i(TAB, "run::" + data);//二番目に呼ばれる

    data++;
    Message msg = handler.obtainMessage();
    msg.arg1 = data;
    handler.sendMessage(msg);
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     // TODO 自動生成された catch ブロック
     e.printStackTrace();
    }
   }
  }

 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(UpdateData updata) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   new Thread(new MyThread()).start();

   handler = new MyHandler(updata);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private UpdateData updata;

  public MyHandler(UpdateData updata) {
   // TODO 自動生成されたコンストラクター・スタブ
   //this.tv = tv;
   this.updata = updata;
  }

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);
   //tv.setText(String.valueOf(msg.arg1));//ここでも変更可能
   updata.update(msg.arg1);
  }

 }
}

時間を表示してみる。
package com.example.bindservice;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

import com.example.bindservice.SampleService.LocalBinder;
import com.example.bindservice.SampleService.UpdateData;

public class MainActivity extends Activity {

 private static final String TAB = "MainActivity";
 private TextView tv;
 private LocalBinder binder;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);

  tv = (TextView) findViewById(R.id.textView1);

  Button button = (Button) findViewById(R.id.button1);
  button.setOnClickListener(new OnClickListener() {

   @Override
   public void onClick(View v) {
    Log.i(TAB, "ボタン2が押された");
    if (binder != null) {
     Log.i(TAB, "binder は null ではない");
     binder.getService(new UpdateData() {

      @Override
      public void update(String data) {
       // TODO 自動生成されたメソッド・スタブ
       tv.setText(data + "");
      }
     });

    } else {
     Log.i(TAB, "binder は null");
    }
   }
  });
 }

 @Override
 public void onStart() {
  Log.i(TAB, "onStart");
  super.onStart();
  // Bind
  Intent intent = new Intent(getApplicationContext(), SampleService.class);
  bindService(intent, mySrviceConnection, Context.BIND_AUTO_CREATE);//サービスをバインド
 }

 @Override
 public void onStop() {
  Log.i(TAB, "onStop");
  super.onStop();
  // Unbind
  unbindService(mySrviceConnection);//サービスをアンバインド
 }

 private ServiceConnection mySrviceConnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   // TODO 自動生成されたメソッド・スタブ
   binder = (SampleService.LocalBinder) service;
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   // TODO 自動生成されたメソッド・スタブ

  }
 };

}
package com.example.bindservice;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SampleService extends Service {

 public interface UpdateData {
  public void update(String data);
 }

 private static final String TAB = "SampleService";
 private IBinder mBinder = new LocalBinder();

 public class LocalBinder extends Binder {

  void getService(UpdateData updata) {
   Log.i(TAB, "LocalBinder");//
   //tv.setText("setData から変更");//ここでも変更可能

   //new Thread(new MyThread()).start();

   MyHandler handler = new MyHandler(updata);
   handler.sendEmptyMessage(1);
  }
 }

 @Override
 public IBinder onBind(Intent intent) {
  // TODO 自動生成されたメソッド・スタブ
  Log.i(TAB, "onBind");//起動時に呼ばれる

  return mBinder;
 }

 @Override
 public void onDestroy() {
  Log.i(TAB, "onDestroy");
 }

 public static class MyHandler extends Handler {
  private UpdateData updata;

  public MyHandler(UpdateData updata) {
   // TODO 自動生成されたコンストラクター・スタブ
   //this.tv = tv;
   this.updata = updata;
  }

  @Override
  public void handleMessage(Message msg) {
   Log.i(TAB, "handleMessage::" + msg);

   GregorianCalendar gc = (GregorianCalendar) GregorianCalendar.getInstance(TimeZone.getTimeZone("Asia/Tokyo"));
   String data = gc.get(Calendar.HOUR_OF_DAY) + ":" + gc.get(Calendar.MINUTE) + ":" + gc.get(Calendar.SECOND);

   sendEmptyMessageDelayed(1, 1000);
   
   updata.update(data);
  }

 }
}