android 在bindService()之后未创建(或连接)服务

qvsjd97n  于 2023-03-21  发布在  Android
关注(0)|答案(4)|浏览(147)

我有一个广播用户当前位置的简单服务,我想使用绑定机制来控制服务的生命周期,但是服务就是没有启动。
我做错了什么?

public class GPSActivity extends ListActivity {
...
protected void onResume() {
        super.onResume();

        Log.i("Service", "Service bound");
        Intent intent = new Intent(this, LocationService.class);
        bindService(intent, service_connection , Context.BIND_AUTO_CREATE);
    }

protected void onPause() {
        if (dataUpdateReceiver!=null)
            unregisterReceiver(dataUpdateReceiver);
        unbindService(service_connection);
        super.onPause();
    }
class LocationServiceConnection implements ServiceConnection{
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i("Service", "Service Connected");
        }
                public void onServiceDisconnected(ComponentName name) {

        }
    }
}

LocalBinder.java

public class LocalBinder<S> extends Binder {
    private String TAG = "LocalBinder";
    private  WeakReference<S> mService;

    public LocalBinder(S service){
        mService = new WeakReference<S>(service);
    }

    public S getService() {
        return mService.get();
    }
}

LocationService.java

public class LocationService extends Service {
    public void onCreate() {
        initLocationListener();
        Log.i("Location Service","onCreate()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Location Service", "Received start id " + startId + ": " + intent);
        return START_NOT_STICKY;
    }

    private final IBinder mBinder = new LocalBinder<LocationService>(this);
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

AndroidManifest.xml

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    ...

    <service android:name=".LocationService">
    </service>
</application>

**编辑:**由于NickT的回答,已修复。

清单条目没有Intent筛选器或正确的名称

<service
   android:enabled="true"
   android:name="com.android.gps.services.LocationService">
   <intent-filter>
          <action android:name="com.android.gps.services.LocationService" />
   </intent-filter>
</service>

我用于绑定的Intent类似于您在启动Activity时需要使用的Intent。正确的Intent是:

Intent intent = new Intent("com.android.gps.services.LocationService");
5gfr0r5j

5gfr0r5j1#

onStartCommand仅在显式启动服务时执行,看起来您只是想绑定到它,这很好。不过我看不出你已经正确地设置了服务连接。我正在发布我的存根程序,它展示了如何绑定到一个服务并通过绑定器调用服务中的一个方法。你可能想运行这个程序并查看各种日志消息的顺序。显然,您需要添加BroadcastReceiver和onLocationChaged代码,使其对您有用。
活动

package com.servtest.test;

import com.servtest.test.LocationService.LocalBinder;
import android.app.Activity;
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.util.Log;

public class ServiceTestActivity extends Activity {

    boolean mServiceConnected = false;
    boolean mBound = false;
    private LocationService mLocnServ;

    ServiceConnection mServconn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("SVTEST", "Activity service connected");
            LocalBinder binder = (LocalBinder) service;
            mLocnServ = binder.getService();
            // Can't call this methodInTheService UNTIL IT'S BOUND!
            mLocnServ.methodInTheService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d("SVTEST", "Activity service disconnected");
            mBound = false;
        }
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.d("SVTEST", "Activity onStart");
        mServiceConnected = bindService(new Intent(
                "com.servtest.test.LOCATIONSERVICE"), mServconn,
                Context.BIND_AUTO_CREATE);
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.d("SVTEST", "Activity onResume");
    }
    @Override
    public void onPause() {
        Log.d("SVTEST", "Activity onPause");
        super.onPause();
    }
    @Override
    public void onStop() {
        Log.d("SVTEST", "Activity onStop");
        if (mBound) {
            unbindService(mServconn);
            mBound = false;
        }
        super.onStop();
    }

}

服务

package com.servtest.test;

import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

public class LocationService extends Service implements LocationListener {

    private final IBinder mBinder = new LocalBinder();

    @Override
    public void onLocationChanged(Location arg0) {}
    @Override
    public void onProviderDisabled(String arg0) {}
    @Override
    public void onProviderEnabled(String arg0) {}
    @Override
    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}

    @Override
    public IBinder onBind(Intent intent) {
        Log.d("SVTEST", "Loc service ONBIND");
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.d("SVTEST", "Loc service ONUNBIND");
        return super.onUnbind(intent);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Won't run unless it's EXPLICITLY STARTED
        Log.d("SVTEST", "Loc service ONSTARTCOMMAND");
        return super.onStartCommand(intent, flags, startId);
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("SVTEST", "Loc service ONDESTROY");
    }

    public class LocalBinder extends Binder {
        LocationService getService() {
            // Return this instance of LocalService so clients can call public methods
            return LocationService.this;
        }
    }

    public void methodInTheService() {
        // A method you can call in the service
        Log.d("SVTEST", "Loc service EXECUTING THE METHOD");
    }
}

宣言

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.servtest.test"
    android:versionCode="1"
    android:versionName="1.0" >
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".ServiceTestActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:enabled="true"
            android:name="LocationService">
            <intent-filter>
                <action android:name="com.servtest.test.LOCATIONSERVICE" />
            </intent-filter>
        </service>
    </application>
</manifest>

希望这能帮上忙

hsvhsicv

hsvhsicv2#

我让我的Activity实现了ServiceConnection,并像这样绑定:

bindService( new Intent( this, Service.class ), this, Context.BIND_AUTO_CREATE );

然后在Activity中处理onServiceConnected()onServiceDisconnected()的回调

hfwmuf9z

hfwmuf9z3#

调用bindService时,可能会出现以下错误:
ActivityManager java.lang.ClassCastException: android.os.BinderProxy cannot be cast to com.android.server.am.ActivityRecord$Token
检查logcat的输出。
这是Android的一个bug。
要解决此问题,请使用 getApplicationContext().bindService(...)

goucqfw6

goucqfw64#

我遇到的一个问题是,我在服务清单中设置了android:enabled="false",这意味着您的应用也无法绑定,而是:

<service
    android:name=".ServiceName"
    android:enabled="true"
    android:exported="..." />

根据文件:
服务是否可以由系统示例化-如果可以,则为“true”,否则为“false”。默认值为“true”。
我犯了一个错误,认为我的应用程序正在进行示例化,而不是系统。

相关问题