Android:绑定到远程服务

时间:2016-09-27 15:26:33

标签: android android-service android-service-binding

我正在构建一个远程服务和一个客户端应用程序,目标是在Nexus 6P设备上执行的API 24。我有一个远程服务,在启动时自动启动。以下是代码片段:

远程服务清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="a.b.c">

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <receiver
            android:name=".MyBroadcastReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <service android:name=".MyService" >
            <intent-filter>
                <action android:name="a.b.c.MY_INTENT" />
            </intent-filter>
        </service>

        <activity android:name=".MyActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

远程服务

package a.b.c;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class MyService extends Service
{
    @Override
    public IBinder onBind(Intent intent) {
        return null;
        // EDIT: see StackOverflow answers/comments below:
        // Returning an IBinder here solves the problem.
        // e.g. "return myMessenger.getBinder()" where myMessenger
        // is an instance of Android's Messenger class.
    }

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

远程广播接收器

package a.b.c;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
            Intent serviceIntent = new Intent(context, MyService.class);
            context.startService(serviceIntent);
        }
    }
}

远程活动 (Android Studio坚持存在活动)

package a.b.c;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MyActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);
    }
}

然后我有一个单独的项目来在尝试绑定到远程服务的不同包中实现客户端活动。以下是代码片段:

客户端清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="x.y.z">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".ClientActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>

客户活动

package x.y.z;

import android.app.ActivityManager;
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.support.v7.app.AppCompatActivity;
import android.util.Log;

public class ClientActivity extends AppCompatActivity
{
    private final String TAG = "ClientActivity";

    private ServiceConnection mMyServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "ServiceConnection onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "ServiceConnection onServiceDisconnected");
        }
    };

    private boolean isServiceRunning(String className) {
        ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (className.equals(serviceInfo.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    private void bindMyService() {
        Intent intent = new Intent("a.b.c.MY_INTENT");
        intent.setPackage("a.b.c");
        bindService(intent, mMyServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_client);
        if (isServiceRunning("a.b.c.MyService")) {
            bindMyService();
        }
        else {
            Log.e(TAG, "Service is not running");
        }
    }
}

&#34; isServiceRunning&#34;函数返回true所以我知道a.b.c.MyService正在运行。 bindService函数似乎成功(在Logcat中没有错误)但是从不执行onServiceConnected回调。

如何从Android目标SDK 24中的x.y.z.ClientActivity绑定到a.b.c.Myservice?

谢谢!

1 个答案:

答案 0 :(得分:5)

我在这里看到至少2个问题:

1)您在Intent的调用中使用了“隐式”bindService()(即:您没有明确指定该组件)。如果您的目标是API 21或更高版本,则应该抛出异常。您应该使用“显式”Intent(即:指定Service的包名和类名。)

2)您的Servicenull返回onBind()。这意味着客户端将无法绑定到Service,因为您没有返回IBinder,客户端可以使用该Service. Try to find a how-to or some example code for how to use bound来调用DECLARE @testtable TABLE( ID INT , modifieddate DATETIME2) INSERT INTO @testtable (id, modifieddate) VALUES (1, '9/29/2016 3:24:24 PM'), (2, '2/01/2016 3:24:24 PM'), (3, '6/25/2016 3:24:24 PM') SELECT * FROM @testtable SELECT * FROM @testtable WHERE CAST(modifieddate AS DATETIME2) = '09/29/2016 3:24:24 PM' SELECT * FROM @testtable WHERE modifieddate = '9/29/2016 3:24:24 PM' SELECT * FROM @testtable WHERE modifieddate = CAST('09/29/2016 3:24:24 PM' AS DATETIME2) 服务上的方法。