2012-07-23 15 views
3

我有一個活動,我想用它來顯示從我的服務發送的數據。每次服務向活動發送消息時,活動都會更新文本視圖。用戶可以使用活動中的按鈕啓動和停止服務(服務由用戶明確啓動/停止)。目前,我的活動綁定到onResume()中的服務,並在onDestroy()中取消綁定,這似乎正在工作。如何將我的Activity綁定到我當前在Android中運行的Service?

當我啓動服務時,按下後退按鈕,然後再次嘗試重點活動時,會出現問題。我遇到了一項新的活動,該活動並未被服務更新,但似乎能夠向服務發送消息(我已經注意到這些來自我的處理程序中的日誌(這個短語使我發笑的男孩)]。理想情況下,我希望只有一個活動實例存在並保持綁定到服務,但我絕對不希望看到活動跟不上更新。我用<activity android:launchMode="singleTop">更新了我的清單,但我不確定這對事情有什麼幫助。我能做些什麼來確保我的活動重新恢復到現有的服務實例,以便以後恢復? (我想通過消息傳遞實現這一點,我不想實現數據庫或使用sharedprefereces這個位)。我在下面包括我的代碼 - 我對服務比較陌生,所以對我來說很簡單。乾杯。

可選額外: 我的目標是從startService()開始持續運行的服務,並且活動的重點是可選的,但會立即顯示服務的最新信息。我相信我正在尋找的是前臺服務。這不是問題的一部分,但請讓我知道,如果你認爲你的答案可能會阻止我實現這一點。

MainActivity.java:

public class MainActivity extends Activity 
{ 
    private static final String debug = "MainActivity"; 
    private boolean bound = false; 
    TextView mTextView; 
    protected Messenger outMessenger; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Log.i(debug, "onCreate called"); 
     mTextView = (TextView) findViewById(R.id.textView1); 

     Button bind = (Button) findViewById(R.id.bind); 
     Button unbind = (Button) findViewById(R.id.unbind); 

     bind.setOnClickListener(new OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       Message message = new Message(); 
       Bundle bundle = new Bundle(); 
       bundle.putString("ACTION", "START"); 
       message.setData(bundle); 
       try 
       { 
        outMessenger.send(message); 
       } catch (RemoteException e) 
       { 
        Log.d(debug, "She can't reach the service captain!"); 
       } 
      } 
     }); 

     unbind.setOnClickListener(new OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       Message message = new Message(); 
       Bundle bundle = new Bundle(); 
       bundle.putString("ACTION", "STOP"); 
       message.setData(bundle); 
       try 
       { 
        outMessenger.send(message); 
       } catch (RemoteException e) 
       { 
        Log.d(debug, "She can't reach the service captain!"); 
       } 
      } 
     }); 
    } 

    @Override 
    public void onPause() 
    { 
     super.onPause(); 
    } 

    @Override 
    public void onResume() 
    { 
     super.onResume(); 
     doBindService(); 
    } 

    public void onDestroy() 
    { 
     super.onDestroy(); 
     Log.i(debug, "onDestroy Called"); 
     doUnbindService(); 
    } 

    private void doBindService() 
    { 
     Log.i(debug, "Attempting to bind"); 
     bound = true; 
     Intent i = new Intent(this, MyService.class); 
     i.putExtra("MESSENGER", new Messenger(mHandler)); 
     bindService(i, mConnection, Context.BIND_AUTO_CREATE); 
    } 

    private void doUnbindService() 
    { 
     Log.i(debug, "Attempting to unbind"); 
     if (bound) 
     { 
      bound = false; 
      unbindService(mConnection); 
     } 
    } 

    private Handler mHandler = new Handler() 
    { 
     public void handleMessage(Message message) 
     { 
      Log.d(debug, "Got a message!"); 
      Bundle data = message.getData(); 
      if (data != null) 
      { 
       Log.i(debug, "This data ain't null!"); 
       if (data.containsKey("MESSAGE")) 
       { 
        mTextView.setText(data.getString("MESSAGE")); 
       } 
      } 
     } 
    }; 

    private ServiceConnection mConnection = new ServiceConnection() 
    { 
     public void onServiceConnected(ComponentName className, IBinder binder) 
     { 
      Log.i(debug, "Service connected!"); 
      outMessenger = new Messenger(binder); 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName className) 
     { 
      Log.d(debug, "Service Disconnected!"); 
     } 
    }; 
} 

MyService.java

public class MyService extends Service 
{ 
    private static final String debug = "MyService"; 
    private Messenger inMessenger = new Messenger(new IncomingHandler()); 
    Messenger outMessenger; 
    private boolean bound = false; 
    int secret = 0; 

    @Override 
    public void onCreate() 
    { 
     Log.d(debug , "MyService Created"); 
    } 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) 
    { 
     Log.d(debug , "onStartCommand called"); 
     handleCommand(intent); 
     return START_STICKY; 
    } 

    Handler handler = new Handler(); 
    public boolean running; 
    void handleCommand(Intent i) 
    { 
     Runnable r = new Runnable() 
     { 
      public void run() 
      { 
       updateResultsInUi(); 
       if (running) 
       { 
        handler.postDelayed(this, 500); 
       } 
      } 
     }; 
     r.run(); 
    } 

    void updateResultsInUi() 
    { 
     Bundle bundle = new Bundle(); 
     bundle.putString("MESSAGE", 
       Integer.toString(secret = ++secret % 10)); 
     Message message = new Message(); 
     message.setData(bundle); 

     if (bound) 
     { 
      try 
      { 
       outMessenger.send(message); 
      } 
      catch (RemoteException e) 
      { 
       Log.d(debug, "Messaging failed"); 
      } 
     } 
     else 
     { 
      Log.d(debug, "Not connected, so not messaging!"); 
     } 

    } 

    @Override 
    public IBinder onBind(Intent intent) 
    { 
     Log.i(debug, "Bound"); 
     bound = true; 
     Bundle extras = intent.getExtras(); 
     outMessenger = (Messenger) extras.get("MESSENGER"); 
     return inMessenger.getBinder(); 
    } 

    @Override 
    public void onRebind(Intent i) 
    { 
     bound = true; 
     Bundle extras = i.getExtras(); 
     outMessenger = (Messenger) extras.get("MESSENGER"); 
    } 

    @Override 
    public boolean onUnbind(Intent i) 
    { 
     Log.d(debug, "onUnbind() called."); 
     bound = false; 
     outMessenger = null; 
     return true; 
    } 

    class IncomingHandler extends Handler 
    { 
     @Override 
     public void handleMessage(Message msg) 
     { 
      Log.d(debug, "Got message"); 
      Bundle data = msg.getData(); 
      if (data.containsKey("ACTION")) 
      { 
       if ("START".equals(data.getString("ACTION"))) 
       { 
        if (!running) 
        { 
         running = true; 
         Intent i = new Intent(getApplicationContext(), MyService.class); 
         startService(i); 
        } 
        else 
        { 
         Log.d(debug, "We're already up and running!"); 
        } 
       } 
       else if ("STOP".equals(data.getString("ACTION"))) 
       { 
        running = false; 
        Intent i = new Intent(getApplicationContext(), MyService.class); 
        stopService(i); 
       } 
      } 
     } 
    } 
} 

AndroidManifest.xml中

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.tests.servicetest" 
    android:versionCode="1" 
    android:versionName="1.0" > 
    <uses-sdk 
     android:minSdkVersion="8" 
     android:targetSdkVersion="15" /> 
    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" 
     android:theme="@style/AppTheme" > 
     <activity 
      android:name="com.tests.servicetest.MainActivity" 
      android:label="@string/title_activity_main" 
      android:launchMode="singleTop" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
     <service 
      android:name="com.tests.servicetest.MyService" 
      android:process=":inaneService"> 
     </service> 
    </application> 
</manifest> 

而對於那些你們誰想要運行它,activity_main.xml中

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerHorizontal="true" 
     android:layout_centerVertical="true" 
     android:padding="@dimen/padding_medium" 
     android:text="@string/hello_world" 
     tools:context=".MainActivity" /> 

    <Button 
     android:id="@+id/bind" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignLeft="@+id/textView1" 
     android:layout_below="@+id/textView1" 
     android:text="Start" /> 

    <Button 
     android:id="@+id/unbind" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignLeft="@+id/textView1" 
     android:layout_below="@+id/bind" 
     android:text="Stop" /> 

</RelativeLayout> 
+0

的問題是,在onRebind意圖是不是新的傳遞給bindService,但原來的一個,在firt綁定使用。喬納斯的答案是要走的路。 – ecdpalma 2013-04-24 14:30:13

回答

4

你可能想看看這個:https://github.com/JonasGroeger/GPSService

+0

乾杯哥們,這讓它表現得很好!我認爲這是一種美麗的服務方式,但在任何書籍/教程中我都沒有看到它 - 你知道這對於這樣的應用程序來說通常是不錯的體系結構嗎? – Chironex 2012-07-26 15:42:41

+0

不幸的是,沒有。但是,也許你會爲此提出另一個問題。我想知道這也是:) – 2012-07-27 17:36:26

相關問題