2016-09-27 5 views
3

Nexus 6P 기기에서 실행되는 API 24에서 원격 서비스 및 클라이언트 애플리케이션을 타겟팅하고 있습니다. 부팅 할 때 자동으로 시작되는 원격 서비스가 있습니다. 여기에 코드 조각은 다음과 같습니다Android : 원격 서비스에 바인딩

원격 서비스 매니페스트

<?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); 
     } 
    } 
} 

원격 활동

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"); 
     } 
    } 
} 

내가 a.b.c.MyService가 실행되고 있는지 알 수 있도록 "isServiceRunning"함수가 true를 반환합니다. bindService 함수가 성공한 것으로 보이지만 (Logcat에서는 오류가 발생하지 않음) onServiceConnected 콜백이 실행되지 않습니다.

Android 대상 SDK 24의 x.y.z.ClientActivity에서 a.b.c.Myservice에 어떻게 바인딩합니까?

감사합니다!

답변

2

나는 여기에 최소 2 문제를 참조하십시오 당신은 통화에서 "암시"Intent을 사용하는

1) bindService()에 (예 : 당신이) 명시 적 구성 요소를 지정하지 않았습니다. API 21 이상을 타겟팅하는 경우 예외가 발생합니다. "명시 적"Intent을 사용해야합니다 (예 : Service의 패키지 이름과 클래스 이름 지정).

2) ServicenullonBind()에서 반환합니다. 즉, 을 반환하지 않아 클라이언트가 Service에 바인딩 할 수 없으므로 클라이언트가 Service. Try to find a how-to or some example code for how to use bound 서비스의 메소드를 호출 할 수 있습니다.

+1

광고 1) 실제로는 : 'intent.setPackage ("a.b.c");'를 호출하면 인 텐트는 "명시 적"이됩니다. – pskink

+0

@pskink 정말요? 패키지 이름으로 충분합니까? 나는 그 사실을 알지 못했지만 기꺼이 바로 잡을 수있다. –

+0

네, 그 의도가 명백한 패키지로 제한되어 있기 때문에 충분합니다. 당연히 그 의도를 고유하게 만드는 동작을 제공하여 "더 명백하게"만들 필요가 있습니다. – pskink