Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service allocate lots of memory?

I've been using Android open source service example. I just need to use it to send notification to user, but strange, it allocates lots of memory. I checked in Running Services, and it is almost 20MB (if i set ACTION_BACKGROUND) or 30MB (if i set ACTION_FOREGROUND)...

What should i do to reduce this memory usage?

I've already read this discussion I have no bitmap or webview.

Here's my service:

/**
* This is an example of implementing an application service that can
* run in the "foreground".  It shows how to code this to work well by using
* the improved Android 2.0 APIs when available and otherwise falling back
* to the original APIs.  Yes: you can take this exact code, compile it
* against the Android 2.0 SDK, and it will against everything down to
* Android 1.0.
*/

public class NotificationService extends Service {

static final String ACTION_FOREGROUND = "com.example.android.apis.FOREGROUND";
static final String ACTION_BACKGROUND = "com.example.android.apis.BACKGROUND";

private static final Class<?>[] mSetForegroundSignature = new Class[] {
    boolean.class};
private static final Class<?>[] mStartForegroundSignature = new Class[] {
    int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
    boolean.class};

//    protected NotificationManager mNM;

private Method mSetForeground;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mSetForegroundArgs = new Object[1];
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];

void invokeMethod(Method method, Object[] args) {
    try {
        method.invoke(this, args);
    } catch (InvocationTargetException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    } catch (IllegalAccessException e) {
        // Should not happen.
        Log.w("ApiDemos", "Unable to invoke method", e);
    }
}

/**
 * This is a wrapper around the new startForeground method, using the older
 * APIs if it is not available.
 */
void startForegroundCompat(int id, Notification notification) {
    // If we have the new startForeground API, then use it.
    if (mStartForeground != null) {
        mStartForegroundArgs[0] = Integer.valueOf(id);
        mStartForegroundArgs[1] = notification;
        invokeMethod(mStartForeground, mStartForegroundArgs);
        return;
    }

    // Fall back on the old API.
    mSetForegroundArgs[0] = Boolean.TRUE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
    // mNM.notify(id, notification);
}

/**
 * This is a wrapper around the new stopForeground method, using the older
 * APIs if it is not available.
 */
void stopForegroundCompat(int id) {
    // If we have the new stopForeground API, then use it.
    if (mStopForeground != null) {
        mStopForegroundArgs[0] = Boolean.TRUE;
        invokeMethod(mStopForeground, mStopForegroundArgs);
        return;
    }

    // Fall back on the old API.  Note to cancel BEFORE changing the
    // foreground state, since we could be killed at that point.
    // mNM.cancel(id);
    mSetForegroundArgs[0] = Boolean.FALSE;
    invokeMethod(mSetForeground, mSetForegroundArgs);
}

@Override
public void onCreate() {
    // mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
    try {
        mStartForeground = getClass().getMethod("startForeground",
                mStartForegroundSignature);
        mStopForeground = getClass().getMethod("stopForeground",
                mStopForegroundSignature);
        return;
    } catch (NoSuchMethodException e) {
        // Running on an older platform.
        mStartForeground = mStopForeground = null;
    }
    try {
        mSetForeground = getClass().getMethod("setForeground",
                mSetForegroundSignature);
    } catch (NoSuchMethodException e) {
        throw new IllegalStateException(
                "OS doesn't have Service.startForeground OR Service.setForeground!");
    }
}

@Override
public void onDestroy() {
    // Make sure our notification is gone.
    stopForegroundCompat(1);
}

// This is the old onStart method that will be called on the pre-2.0
// platform.  On 2.0 or later we override onStartCommand() so this
// method will not be called.
@Override
public void onStart(Intent intent, int startId) {
    handleCommand(intent);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    handleCommand(intent);
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return  START_STICKY;
}

@Override
public void onRebind(Intent intent) {
    super.onRebind(intent);
    handleCommand(intent);
}

void handleCommand(Intent intent) {
    if (intent == null)
        return;

    if (ACTION_FOREGROUND.equals(intent.getAction())) {

        DBHelper db = new DBHelper(this);

        String lastTime = db.getLastVisitTime();
        if(!lastTime.equals("-1")) {
            new Notifications(this).InviteUser();
        }

        String target = db.getTargetValue();
        if(target.equals("")) {
            new Notifications(this).TargetlessNotification();
        }

        db.close();

        /*
        // In this sample, we'll use the same text for the ticker and the expanded notification 
        CharSequence text = getString(R.string.app_name); 
        CharSequence description = getString(R.string.recall_user);

        // Set the icon, scrolling text and timestamp
        Notification notification = new Notification(R.drawable.icon, text, System.currentTimeMillis());

        // The PendingIntent to launch our activity if the user selects this notification PendingIntent
        contentIntent = PendingIntent.getActivity(this, 1, new Intent(this, YKEYarinaSaklaActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        notification.setLatestEventInfo(this, text, description, contentIntent);

        // Set properties of notification 
        notification.flags = Notification.FLAG_INSISTENT | Notification.FLAG_AUTO_CANCEL; 
        notification.defaults |= Notification.DEFAULT_ALL;

        startForegroundCompat(1, notification);
        */


    } else if (ACTION_BACKGROUND.equals(intent.getAction())) {
        stopForegroundCompat(1);
    }
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}
}

P.S.: I don't know if it's relevant or not but i'm starting this service onDestroy of my app, so it'll send notification to user on a specific time with AlarmManager. (So it should not be killed to avoid AlarmManager deleting my notification.)

like image 258
yahya Avatar asked Nov 03 '22 16:11

yahya


1 Answers

I've tried to simplfy my service as possible as i can, but the situation is still the same... Then i realize that somehow, usage of memory decrease by itself... So, if i have no option, i could except that.

public class NotificationService2 extends Service{

private String target, lastTime, notifCheck, notifCheck2;

@Override
public void onStart(Intent intent, int startId) {

    Bundle extras = intent.getExtras();
    if(extras != null) {
        this.lastTime = extras.getString("lastTime");
        this.target = extras.getString("target");
        this.notifCheck = extras.getString("notifCheck");
        this.notifCheck2 = extras.getString("notifCheck2");
    }

    handleCommand(intent);

    super.onStart(intent, startId);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Bundle extras = intent.getExtras();
    if(extras != null) {
        this.lastTime = extras.getString("lastTime");
        this.target = extras.getString("target");
        this.notifCheck = extras.getString("notifCheck");
        this.notifCheck2 = extras.getString("notifCheck2");
    }

    handleCommand(intent);

    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
}

@Override
public IBinder onBind(Intent intent) {
    handleCommand(intent);
    return null;
}

@Override
public void onRebind(Intent intent) {
    super.onRebind(intent);
    handleCommand(intent);
}

void handleCommand(Intent intent) {
    if (intent == null)
        return;

    String lastTime = this.lastTime;
    String notifCheck = this.notifCheck;
    String target = this.target;
    String notifCheck2 = this.notifCheck2;

    if(lastTime != null && notifCheck != null) {
        if(!lastTime.equals("-1") && !notifCheck.equals("1")) 
            new Notifications(this).InviteUser();
    } else this.stopSelf();

    if(target != null && notifCheck2 != null) {
        if(target.equals("") && !notifCheck2.equals("1")) 
            new Notifications(this).TargetlessNotification();
    } else this.stopSelf();

}

}
like image 194
yahya Avatar answered Nov 09 '22 16:11

yahya