如何将我的Activity绑定到Android中当前运行的服务?

时间:2012-07-23 19:00:34

标签: android binding android-service

我有一项活动,我想用它来显示从我的服务发送的数据。每次服务向活动发送消息时,活动都会更新文本视图。用户能够使用活动中的按钮启动和停止服务(用户明确地启动/停止服务)。目前,我的活动绑定到onResume()中的服务,并在onDestroy()中取消绑定,这似乎暂时正在工作。

启动服务时出现问题,按后退按钮,然后尝试再次聚焦活动。我遇到了一个新的活动,该活动没有被服务更新,但似乎能够向服务发送消息(我已经注意到这来自我的处理程序中的日志[男孩那句话让我发笑!])。理想情况下,我只希望我的活动的一个实例存在并保持与服务绑定,但我绝对不希望看到活动无法跟上更新。我用<activity android:launchMode="singleTop">更新了我的清单,但我不确定这有多大帮助。我可以做些什么来确保我的活动在以后恢复时重新绑定到现有的服务实例? (我希望通过消息传递来实现这一点,我不想实现数据库或使用共享优先级)。我在下面包含了我的代码 - 我对服务比较陌生,所以对我很轻松。欢呼声。

可选额外: 我的目标是从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>

1 个答案:

答案 0 :(得分:4)

您可能需要查看此内容:https://github.com/JonasGroeger/GPSService