如何将我的活动绑定到Android中当前运行的服务?
我有一个活动,我想用它来显示从我的服务发送的数据。每次服务向活动发送消息时,活动都会更新textview。用户能够使用活动中的按钮启动和停止服务(服务由用户显式启动/停止)。目前,我的活动绑定到onResume()中的服务,并在onDestroy()中解除绑定,这似乎暂时有效 当我启动服务,按下后退按钮,然后再次尝试聚焦活动时,问题就会出现。我遇到了一个新的活动,它没有被服务更新,但似乎能够向服务发送消息(我从我的处理程序中的日志中注意到了这一点[男孩,这句话让我发笑!)。理想情况下,我只希望我的活动的一个实例存在并保持与服务的绑定,但我绝对不希望看到一个活动没有跟上更新。我已经用如何将我的活动绑定到Android中当前运行的服务?,android,binding,android-service,Android,Binding,Android Service,我有一个活动,我想用它来显示从我的服务发送的数据。每次服务向活动发送消息时,活动都会更新textview。用户能够使用活动中的按钮启动和停止服务(服务由用户显式启动/停止)。目前,我的活动绑定到onResume()中的服务,并在onDestroy()中解除绑定,这似乎暂时有效 当我启动服务,按下后退按钮,然后再次尝试聚焦活动时,问题就会出现。我遇到了一个新的活动,它没有被服务更新,但似乎能够向服务发送消息(我从我的处理程序中的日志中注意到了这一点[男孩,这句话让我发笑!)。理想情况下,我只希望我
更新了我的清单,但我不确定这对这件事有多大帮助。我可以做些什么来确保我的活动在以后恢复时重新绑定到服务的现有实例?(我想通过消息传递实现这一点,我不想实现数据库或使用SharedPreferes来实现这一点)。我在下面列出了我的代码——我对服务比较陌生,所以对我放松点。干杯
可选额外费用:
我的目标是一个从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>
你可能想看看这个:干杯,伙计,这就是它的表现!我认为这是一种很好的服务方法,但我以前在任何书籍/教程中都没有见过这种方法-您知道这对于此类应用程序来说是否通常是一种很好的体系结构吗?不幸的是,不是。不过,也许您会问另一个问题。我也想知道这一点:)问题是onRebind中的意图不是传递给bindService的新的意图,而是第一次绑定中使用的原始意图。乔纳斯的答案是正确的。