2012-09-05 9 views
5

Sto usando un esempio di servizio open source Android. Ho solo bisogno di usarlo per inviare notifiche all'utente, ma strano, alloca molta memoria. Ho controllato in Running Services, ed è quasi 20MB (se ho impostato ACTION_BACKGROUND) o 30MB (se ho impostato ACTION_FOREGROUND) ...Il servizio alloca molta memoria?

Cosa devo fare per ridurre questo utilizzo della memoria?

Ho già letto this discussion Non ho bitmap o webview.

Ecco il mio servizio:

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

PS: Non so se è rilevante o no, ma sto iniziando questo servizio OnDestroy di mia app, in modo che lo trasmetteranno notifica utente su un determinato tempo con AlarmManager. (Quindi non dovrebbe essere ucciso per evitare AlarmManager cancellando la mia notifica.)

+1

dati discarica hprof e [Analizza] (http://android-developers.blogspot.in/2011/03/memory-analysis-for-android.html) – nandeesh

+0

Grazie per questo tutorial impressionante. L'ho controllato e, come ho capito, non c'è niente di sbagliato. Ma ancora assegna così tanto:/ – yahya

+0

hai provato a scaricare hprof e verificare quali oggetti stanno prendendo memoria? – nandeesh

risposta

2

Ho cercato di semplificare il mio servizio il più possibile che posso, ma la situazione è sempre la stessa ... Poi mi rendo conto che in qualche modo, l'uso di memoria diminuisce da sola ... Quindi, se non ho scelta, potrei eccetto questo.

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

} 

} 
Problemi correlati