我有一个活动,我想用它来显示从我的服务发送的数据。每次服务向活动发送消息时,活动都会更新文本视图。用户能够使用活动中的按钮启动和停止服务(服务由用户明确启动/停止)。目前,我的活动绑定到 onResume() 中的服务并在 onDestroy() 中取消绑定,这似乎目前正在工作。
当我启动服务,按下后退按钮,然后尝试再次关注活动时,就会出现问题。我遇到了一个新的活动,该活动没有被服务更新,但似乎能够向服务发送消息(我从我的处理程序中的日志中注意到了这一点[男孩,这句话让我发笑!])。理想情况下,我只希望我的活动的一个实例存在并保持绑定到服务,但我绝对不希望看到一个活动跟不上更新。我已经更新了我的清单<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!");
}
};
}
我的服务.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>