2012-09-05 8 views
5

He estado usando el ejemplo de servicio de código abierto de Android. Solo necesito usarlo para enviar notificaciones al usuario, pero extraño, asigna mucha memoria. Me registré en Servicios en ejecución, y es casi 20MB (si configuro ACTION_BACKGROUND) o 30MB (si configuro ACTION_FOREGROUND) ...¿El servicio asigna mucha memoria?

¿Qué debo hacer para reducir este uso de memoria?

Ya leí this discussion No tengo mapa de bits o vista web.

Aquí está mi servicio:

/** 
* 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; 
} 
} 

PD: No sé si es relevante o no, pero estoy empezando este OnDestroy servicio de mi aplicación, por lo que debes enviar una notificación al usuario en un determinado tiempo con AlarmManager. (Entonces no se debe matar para evitar que AlarmManager borre mi notificación.)

+1

datos hprof volcado y [Analizar] (http://android-developers.blogspot.in/2011/03/memory-analysis-for-android.html) – nandeesh

+0

Gracias por este tutorial impresionante. Lo he comprobado, y como entiendo, no hay nada de malo. Pero todavía asigna tanto:/ – yahya

+0

¿Intentó volcar hprof y comprobar qué objetos están tomando memoria? – nandeesh

Respuesta

2

He intentado simplificar mi servicio tanto como puedo, pero la situación sigue siendo la misma ... Entonces me doy cuenta de que de alguna manera, el uso de memoria disminuye por sí mismo ... Entonces, si no tengo otra opción, podría exceptuar eso.

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(); 

} 

} 
Cuestiones relacionadas