How to start an IntentService from a WakefulBroadcastReceiver

22,743

There is no tag as <intentservice> in Application Manifest. IntentService is a subclass of Service, so you need to declare it as service in manifest.


Change

<intentservice 
    android:name="com.example.broadcasttest.MonitorService"
    android:enabled="true" >
        <intent-filter>
            <action android:name="com.example.broadcasttest.MonitorService" />
        </intent-filter>
</intentservice>

to

<service 
    android:name="com.example.broadcasttest.MonitorService"
    android:enabled="true" >
       <intent-filter>
           <action android:name="com.example.broadcasttest.MonitorService" />
       </intent-filter>
</service>
Share:
22,743
overactor
Author by

overactor

I'm currently an apprentice software developer with a broad area of interest and a slight lack of focus. My languages include (in no particular order): Java Javascript Python Delphi Swift

Updated on January 09, 2020

Comments

  • overactor
    overactor over 4 years

    I have an application, which you should be able to recreate entirely and very easily with the code I'll post in this question. Here's the Manifest file:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.broadcasttest"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="19"
            android:targetSdkVersion="21" />
    
        <uses-permission android:name="android.permission.WAKE_LOCK"/>
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
    
            <activity
                android:name="com.example.broadcasttest.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            <receiver
                android:name="com.example.broadcasttest.TestReceiver"
                android:label="@string/app_name"
                android:enabled="true" >
            </receiver>
    
            <intentservice 
                android:name="com.example.broadcasttest.MonitorService"
                android:enabled="true" >
                <intent-filter>
                    <action android:name="com.example.broadcasttest.MonitorService" />
                </intent-filter>
            </intentservice>
        </application>
    
    </manifest>
    

    As you can see, the contains an activity, a (wakeful) broadcast receiver and an intentservice, all in the same package. The activity gets started at launch, here's the code:

    package com.example.broadcasttest;
    
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            sendBroadcast(new Intent(this, TestReceiver.class));
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }
    

    This succesfully triggers the onReceive function of TestReceiver.

    package com.example.broadcasttest;
    
    import android.content.Context;
    import android.content.Intent;
    import android.support.v4.content.WakefulBroadcastReceiver;
    
    public class TestReceiver extends WakefulBroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            //Intent service = new Intent("com.example.broadcasttest.MonitorService");
            Intent service = new Intent(context, MonitorService.class);
            startWakefulService(context, service);
        }
    
    }
    

    This is where things go wrong though, I placed a breakpoint in the onReceive function and it definitely gets called. However, the MonitorService class never gets reached. I placed a breakpoint in the onHandleEvent function, but it seems like it never gets that far. Here's the code for this class:

    package com.example.broadcasttest;
    
    import android.app.IntentService;
    import android.content.Intent;
    
    public class MonitorService extends IntentService {
    
        public MonitorService(String name) {
            super(name);
        }
    
        public MonitorService()
        {
            super("MonitorService");
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                TestReceiver.completeWakefulIntent(intent);
            }
    
        }
    
    }
    

    As you can tell from the commented line in the TestReceiver class, I've tried using an implicit intent instead of an explicit one. I've also read this question and tried everything mentioned there. Am I missing something here? I'm running this on an emulator (Nexus7 API L).

    Is there anything I'm missing here?

  • overactor
    overactor over 9 years
    Thanks, if only I had known that it was that simple. I wonder why I didn't get any sort of error though.