title: Android service execution denied
body: <p>I have a service implemented as a <a href="https://github.com/commonsguy/cwac-wakeful" rel="nofollow noreferrer">WakefulIntentService</a>. It is started every time a proper intent is issued to the <code>BroadcastReceiver</code> responsible by starting it. The service starts in two situations: upon device boot and when a running instance of the service is about to finish and schedules a new execution by asking Android's conventional task scheduler, the <code>AlarmManager</code>, to issue a starter intent at a future time.</p>
  
  <p>The question is, I <a href="https://stackoverflow.com/questions/17073938/android-service-scheduled-on-alarmmanager-not-starting">have been advised</a> not to use <code>android:exported="true"</code> in the service declared in the Manifest file for security reasons. However, omitting it causes the service execution to be denied in one of the test phones (a Samsung S3 running Android 4.1.2):</p>
  
  <pre><code>06-13 11:34:34.181: W/ActivityManager(2270): Permission denied: checkComponentPermission() owningUid=10155
  06-13 11:34:34.181: W/ActivityManager(2270): Permission Denial: Accessing service ComponentInfo{com.mypackage.myapp/com.mypackage.myapp.MyService} from pid=10320, uid=2000 that is not exported from uid 10155
  </code></pre>
  
  <p>Adding <code>android:exported="true"</code> fixes the problem. Is there an alternative to avoid the execution denial without compromising the app's security?</p>
  
  <p>The Manifest xml file:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mypackage.myapp"
      android:versionCode="3"
      android:versionName="1.0"&gt;
  
      &lt;uses-sdk
          android:minSdkVersion="8"
          android:targetSdkVersion="17" /&gt;
  
      &lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /&gt;
      &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
      &lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
      &lt;uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /&gt;
      &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
  
      &lt;application
          android:allowBackup="true"
          android:icon="@drawable/ic"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" &gt;
  
          &lt;receiver android:name=".MyBroadcastReceiver" &gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.BOOT_COMPLETED" /&gt;
                  &lt;category android:name="android.intent.category.DEFAULT" /&gt;
              &lt;/intent-filter&gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="com.mypackage.myapp" /&gt;
              &lt;/intent-filter&gt;
          &lt;/receiver&gt;
  
          &lt;service
              android:name="com.mypackage.myapp.MyService"
              android:exported="true"&gt;
          &lt;/service&gt;
  
      &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p>The <code>BroadcastReceiver</code>:</p>
  
  <pre><code>package com.mypackage.myapp;
  
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  
  import com.commonsware.cwac.wakeful.WakefulIntentService;
  
  public class MyBroadcastReceiver extends BroadcastReceiver {
  
      @Override
      public void onReceive(Context context, Intent intent) {
          WakefulIntentService.sendWakefulWork(context, MyService.class);
      }
  }
  </code></pre>
  
  <p>The service containing the starter intent scheduling code in <code>onDestroy()</code>:</p>
  
  <pre><code>public class MyService extends WakefulIntentService {
  
  (...)
  
      @Override
      public void doWakefulWork(Intent intent) {
          (...)
      }
  
      @Override
      public void onDestroy() {
  
          PendingIntent pi = PendingIntent.getBroadcast(this, 0, new Intent("com.mypackage.myapp"), 0);
  
          AlarmManager am = (AlarmManager)(this.getSystemService(Context.ALARM_SERVICE));
  
          am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, ONE_MINUTE, pi);
  
          super.onDestroy();
      }
  }
  </code></pre>