Question

I'm developing an Air (Flex) Mobile application for Android, which uses Air Native Extension (ANE) to take advantage of some platform functions that otherwise could not be used (at least to my knowledge). One of the platform functions that I want to use are services, specifically services that run as Foreground processes (using the startForeground() method). When I invoke the service from my ANE everything works like a charm, the service is started correctly and it does what it needs to do but the problem is that Android seems to be trying to start it independently from my code, which, of course, results in errors that appear in the LogCat. When I launch the application in debug mode in Flash Builder, and I use it for a while checking that the service works perfectly and no errors are thrown, after I close it from the Flash Builder (not from Eclipse ADT, which I also could) a couple of seconds later, the following errors appear:

01-16 10:56:06.953: E/AndroidRuntime(9757): java.lang.RuntimeException: Unable to start service com.mycompany.myextension.services.MyService@41594a50 with Intent { cmp=air.QOE.debug/com.mycompany.myextension.services.MyService }: java.lang.NullPointerException
01-16 10:56:06.953: E/AndroidRuntime(9757):     at com.mycompany.myextension.services.MyService.onStartCommand(MyService.java:37) 

It seems to be clear that Android tries to start the service but since its design to work inside the ANE -the extension is initialized but its context was already disposed- it crashes because it cannot reach the variables that are initialized within the context, therefore, ending in a crash or error the first time the code uses a context variable (line 37). I would think that this has to do with the way I declared the service in my Android Manifest file. Next is part of the XML:

<application android:debuggable="true">
              <service android:enabled="true" android:exported="true" android:name="com.mycompany.myextension.services.MyService">    
                        <intent-filter>
                                 <action android:name="air.com.mycompany.myextension.DO_CUSTOM_ACTION"/>
                        </intent-filter>
                </service>
</application>

I hope you can tell me if I’m declaring the service incorrectly or if I’m making a mistake elsewhere. I appreciate the help.

EDIT: Service code

package com.mydomain.myapplicationextension.services;

import java.util.Timer;

import com.adobe.fre.FREContext;
import com.mydomain.myapplicationextension.myapplicationextension;
import com.mydomain.myapplicationextension.components.HttpServiceTask;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;

public class MyApplicationService extends Service {

    private Timer timer;  

    @Override
    public IBinder onBind(Intent arg0) {
        // Log.d("MyApplicationService", "onBind()");
        return null;
    }
    
    @Override
    public void onCreate() {
        // Log.d("MyApplicationService", "onCreate()");
        super.onCreate();
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Log.d("MyApplicationService", "onStartCommand(): " + myapplicationextension.applicationID);
                
        Context appContext = myapplicationextension.applicationContext;     
        Intent launchIntent = appContext.getPackageManager().getLaunchIntentForPackage(myapplicationextension.appPackageName);      
        PendingIntent pendingLaunchIntent = PendingIntent.getActivity(appContext, 0, launchIntent, 0);
        
        FREContext extContext = myapplicationextension.extensionContext;
        int icon = extContext.getResourceId("drawable.notification_icon");
        
        Notification notification = new Notification.Builder(appContext)
                                                    .setContentTitle(myapplicationextension.applicationID)
                                                    .setContentText(myapplicationextension.notificationMessage)
                                                    .setSmallIcon(icon)
                                                    .setContentIntent(pendingLaunchIntent)
                                                    .build();
        startForeground(1,notification);
        // Log.d("MyApplicationService", "startForegroundService()");
        
        if(myapplicationextension.checkStatus)
        {
            timer = new Timer("Printer");
            HttpServiceTask serviceTask = new HttpServiceTask(timer, launchIntent,myapplicationextension.statusServiceURL, myapplicationextension.triggerResponse);
            timer.schedule(serviceTask, 0, 2000);
            // Log.d("MyApplicationService", "startTimer()");
        }
        
        return START_STICKY;
    }
    
    @Override
    public void onDestroy() {
        // Log.d("MyApplicationService", "onDestroy():");
        if(myapplicationextension.checkStatus)
        {
            timer.cancel();
            timer = null;
            // Log.d("MyApplicationService", "onDestroy(): timer.cancel():");
        }
        super.onDestroy();
    }
}
Was it helpful?

Solution

When the phone runs out of memory and kills the service before it finishes executing. START_STICKY tells the OS to recreate the service after it has enough memory and call onStartCommand() again with a null intent. START_NOT_STICKY tells the OS to not bother recreating the service again. There is also a third code START_REDELIVER_INTENT that tells the OS to recreate the service AND redelivery the same intent to onStartCommand().

START_STICKY and START_NOT_STICKY

I have an ANE using START_STICKY that keeps launching the service

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top