2015-01-08 19 views
40

Tôi có một ứng dụng một thời gian mà bây giờ tôi gọi một dịch vụ thông qua bộ thu phát sóng (MyStartupIntentReceiver). Các mã trong máy thu phát sóng để gọi dịch vụ là:Mục đích của dịch vụ phải rõ ràng: Intent

public void onReceive(Context context, Intent intent) { 
    Intent serviceIntent = new Intent(); 
    serviceIntent.setAction("com.duk3r.eortologio2.MyService"); 
    context.startService(serviceIntent); 
} 

Vấn đề là trong Android 5.0 Lollipop tôi nhận được lỗi sau (trong các phiên bản Android trước, mọi thứ hoạt động ok):

Unable to start receiver com.duk3r.eortologio2.MyStartupIntentReceiver: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.duk3r.eortologio2.MyService } 

Tôi phải thay đổi điều gì để dịch vụ được khai báo là rõ ràng và bắt đầu bình thường? Đã thử một số câu trả lời trong các chủ đề tương tự khác nhưng mặc dù tôi đã loại bỏ thông báo, dịch vụ sẽ không bắt đầu.

+0

đây có phải là dịch vụ trong ứng dụng của bạn không? – tyczj

+0

có gói com.duk3r.eortologio2 là ứng dụng của tôi. – duk3r

+3

Chỉ có '' trên một thành phần khi bạn muốn ứng dụng của bên thứ ba giao tiếp với thành phần đó. Bạn dường như đã rơi vào cái bẫy giả định rằng bạn cần một '' cho mọi thứ - trong thực tế, bạn thường xuyên cần một ''. Một 'Intent' rõ ràng là khi bạn chỉ định thành phần để nói chuyện trong chính' Intent', thường sử dụng hàm tạo để lấy một đối tượng Java 'Class' làm tham số thứ hai. Điều đó, thay vì ngầm 'Intent' và '' s, là những gì bạn nên sử dụng cho các thành phần cục bộ cho ứng dụng của bạn. – CommonsWare

Trả lời

72

bất kỳ ý định bạn thực hiện cho một dịch vụ, hoạt động vv trong ứng dụng của bạn nên luôn luôn làm theo định dạng này

Intent serviceIntent = new Intent(context,MyService.class); 
context.startService(serviceIntent); 

hoặc

Intent bi = new Intent("com.android.vending.billing.InAppBillingService.BIND"); 
bi.setPackage("com.android.vending"); 

intents ngầm (những gì bạn có trong mã của bạn hiện tại) là được coi là rủi ro bảo mật

+0

thanx tyczj, đã làm cho lỗi biến mất :) – duk3r

+0

điều đó không đúng, câu trả lời của @ kai-chen hoạt động hoàn hảo –

+0

Nếu tôi cần 'bindService' thì sao? –

18

Đặt packageName hoạt động.

intent.setPackage(this.getPackageName()); 
1

Chuyển đổi ý định ngầm đến mục đích rõ ràng sau đó bắt đầu dịch vụ khởi động.

 Intent implicitIntent = new Intent(); 
     implicitIntent.setAction("com.duk3r.eortologio2.MyService"); 
     Context context = getApplicationContext(); 
     Intent explicitIntent = convertImplicitIntentToExplicitIntent(implicitIntent, context); 
     if(explicitIntent != null){ 
      context.startActivity(explicitIntent); 
      } 


    public static Intent convertImplicitIntentToExplicitIntent(Intent implicitIntent, Context context) { 
      PackageManager pm = context.getPackageManager(); 
      List<ResolveInfo> resolveInfoList = pm.queryIntentServices(implicitIntent, 0); 

      if (resolveInfoList == null || resolveInfoList.size() != 1) { 
       return null; 
      } 
      ResolveInfo serviceInfo = resolveInfoList.get(0); 
      ComponentName component = new ComponentName(serviceInfo.serviceInfo.packageName, serviceInfo.serviceInfo.name); 
      Intent explicitIntent = new Intent(implicitIntent); 
      explicitIntent.setComponent(component); 
      return explicitIntent; 
     } 
5

Đối với những người lười biếng như tôi chỉ cần sử dụng

public static Intent createExplicitFromImplicitIntent(Context context, Intent implicitIntent) { 
    // Retrieve all services that can match the given intent 
    PackageManager pm = context.getPackageManager(); 
    List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0); 

    // Make sure only one match was found 
    if (resolveInfo == null || resolveInfo.size() != 1) { 
     return null; 
    } 

    // Get component info and create ComponentName 
    ResolveInfo serviceInfo = resolveInfo.get(0); 
    String packageName = serviceInfo.serviceInfo.packageName; 
    String className = serviceInfo.serviceInfo.name; 
    ComponentName component = new ComponentName(packageName, className); 

    // Create a new intent. Use the old one for extras and such reuse 
    Intent explicitIntent = new Intent(implicitIntent); 

    // Set the component to be explicit 
    explicitIntent.setComponent(component); 

    return explicitIntent; 
} 

Gửi bối cảnh và ý định của bạn trong phương pháp này và nhận được kết quả mục đích sử dụng.

0

Hãy thử điều này. nó làm việc cho tôi. Ở đây MonitoringService là lớp dịch vụ của tôi. Tôi có hai hành động, cho biết dịch vụ dừng hoặc bắt đầu. Tôi gửi giá trị đó từ máy thu phát của mình phụ thuộc vào AIRPLANE_MODE_CHANGED.

@Override 
public void onReceive(Context context, Intent intent) { 
    String action = intent.getAction(); 

    if(Intent.ACTION_AIRPLANE_MODE_CHANGED.equalsIgnoreCase(action)){ 
     boolean isOn = intent.getBooleanExtra("state", false); 
     String serviceAction = isOn? MonitoringService.StopAction : MonitoringService.StartAction; 
     Intent serviceIntent = new Intent(context, MonitoringService.class); 
     serviceIntent.setAction(serviceAction); 
     context.startService(serviceIntent); 
    } 
} 

LƯU Ý: tôi thêm mã sau đây để kích hoạt máy thu phát sóng của tôi tên là: ManageLocationListenerReceiver.

<receiver 
    android:name=".ManageLocationListenerReceiver" 
    android:enabled="true" 
    android:exported="true"> 
    <intent-filter> 
     <action android:name="android.intent.action.AIRPLANE_MODE" /> 
    </intent-filter> 
</receiver> 
Các vấn đề liên quan