2012年11月12日 星期一

Android Application Lifecycle

protected void onCreate(Bundle savedInstanceState);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();

Android Fundamental Components

View
Views are user interface (UI) elements that form the basic building blocks of a user interface. A view could be a button, label, text field, or many other UI elements.  Views are also used as containers for views, which means that there's usually a hierarchy of views in the UI. In the end, everything you see is a view.

Activity
An activity is a user interface concept. An activity usually represents a single screen in your application. It generally contains one or more views, but it doesn’t have to. An activity is pretty much like it sounds—something that helps the user do one thing—and that one thing could be viewing data, creating data, or editing data. Most Android applications have several activities within them.

Intent
An intent generically defines an “intention” to do some work. Intents encapsulate several concepts, so the best approach to understanding them is to see examples of their use.

You can use intents to perform the following tasks:
􀀁 Broadcast a message.
􀀁 Start a service.
􀀁 Launch an activity.
􀀁 Display a web page or a list of contacts.
􀀁 Dial a phone number or answer a phone call.
Intents are not always initiated by your application—they’re also used by the system to notify your application of specific events (such as the arrival of a text message).

Intents can be explicit or implicit. If you simply say that you want to display a URL, the system will decide what component will fulfill the intention. You can also provide specific information about what should handle the intention. Intents loosely couple the action and action handler.

Content Provider
Data sharing among mobile applications on a device is common. Therefore, Android defines a standard mechanism for applications to share data (such as a list of contacts) without exposing the underlying storage, structure, and implementation. Through content providers, you can expose your data and have your applications use data from other applications.

Service
Services in Android resemble services you see in Windows or other platforms—they’re background processes that can potentially run for a long time. Android defines two types of services: local services and remote services. Local services are components that are only accessible by the application that is hosting the service. Conversely, remote services are services that are meant to be accessed remotely by other applications running on the device.  An example of a service is a component that is used by an e-mail application to poll for new messages. This kind of service might be a local service if the service is not used by other applications running on the device. If several applications use the service, then it would be implemented as a remote service. The difference is in startService() vs. bindService().  You can use existing services and also write your own services by extending the Service class.

2012年11月11日 星期日

Large Data Files in /mnt/sdcard/Android/data/com.cooliris.media/cache

Recently, I found that my sdcard become full suddenly. 
I remeber that I must have more than 1G left.  So I am looking for which directory are growing too quick. 

Finaly, I found that it is coming from /mnt/sdcard/Android/data/com.cooliris.media/cache. 

This directory contain more than 1G files.  So I delete them to free up the memory.

However, it is growing up quick to use up all the memory in my SDCARD.

At last I found our the reason.  It is coming from cache for my comic.  So I added .nomedia in all of my comic and the problem solved.  It is now only around 50M.


2012年11月9日 星期五

Memory Analyzer for Android Apps

To dump the heap, click on the icon Dump HPROF file. There are many tools for analyzing heap dumps but the one I'm most familiar is the Eclipse Memory Analyzer (MAT). Download it from http://www.eclipse.org/mat/.

MAT can't handle the DDMS heap dumps right away, but there is a converter tool in the Android SDK.

So simply run this command

C:\Android\android-sdk\tools>hprof-conv rawdump.hprof converteddump.hprof




Android Memory Information

adb shell dumpsys meminfo

adb shell dumpsys meminfo system


ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
    pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer> keys = pidMap.keySet();
for(int key : keys)
{
    int pids[] = new int[1];
    pids[0] = key;
    android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
    for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
    {
        Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
        Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
        Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
    }
}

Android Battery Monitor

package com.hong.monitor.battery;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.TextView;
import android.widget.Toast;
public class BatteryMonitorActivity extends Activity {

    private CheckBox ac,usb,charging;
 private TextView battery_level;
   

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        Intent batteryStatus = getApplicationContext().registerReceiver(null, ifilter);      
       
        // Are we charging / charged?
        int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
        boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;

        // How are we charging?
        int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
        boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;
        boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
       
        ac = (CheckBox) findViewById(R.id.ac);
        usb = (CheckBox) findViewById(R.id.usb);
        charging = (CheckBox) findViewById(R.id.charge);
       
        ac.setChecked(acCharge);
        usb.setChecked(usbCharge);
        charging.setChecked(isCharging);
       
        int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
        int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        float batteryPct = level / (float)scale;
        int temp = batteryStatus.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1);
        int voltage = batteryStatus.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
        char c=186;

        int health = batteryStatus.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
       
        String shealth;
        switch(health) {
/*       
         case BatteryManager.BATTERY_HEALTH_COLD: // for level 11
          shealth = "Battery Cold";
         break;
*/       
         case BatteryManager.BATTERY_HEALTH_DEAD:
          shealth = "Battery Dead/";
          break;
         case BatteryManager.BATTERY_HEALTH_GOOD:
          shealth = "Battery Good/";
          break;
         case BatteryManager.BATTERY_HEALTH_OVERHEAT:
          shealth = "Battery Overheat/";
          break;
         case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
          shealth = "Battery Over Voltage/";
          break;
         case BatteryManager.BATTERY_HEALTH_UNKNOWN:
          shealth = "Battery Unknown/";
          break;
         case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
          shealth = "Battery Unspecified failure/";
          break;
         default:
          shealth = "Battery Other/";
        }
       
        battery_level = (TextView) findViewById(R.id.bat_level);
        battery_level.setText(shealth + level + "%/" + temp/10.0 + c + "C/" + voltage + "mV");
    }
    public class PowerConnectionReceiver extends BroadcastReceiver {   
     @Override   
     public void onReceive(Context context, Intent intent) {        
      int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);       
      boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL;           
      int chargePlug = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);    
     
      boolean usbCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_USB;       
      boolean acCharge = chargePlug == BatteryManager.BATTERY_PLUGGED_AC;
            ac.setChecked(acCharge);
            usb.setChecked(usbCharge);
            charging.setChecked(isCharging);
          
      if(isCharging)
          Log.i("PowerConnectionReceiver", "Charging!");
      else
          Log.i("PowerConnectionReceiver", "Not Charging!");
     
      if(usbCharge)
          Log.i("PowerConnectionReceiver", "USB Charging!");
      if(acCharge)
       Log.i("PowerConnectionReceiver", "AC Charging!");
      Toast.makeText(getApplicationContext(),"ChargePlug: " + chargePlug,Toast.LENGTH_SHORT).show();
     }
    }
    public class BatteryLevelReceiver extends BroadcastReceiver {   
     @Override   
     public void onReceive(Context context, Intent battery) {  
      int level = battery.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
      int scale = battery.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
      float batteryPct = level / (float)scale;     
      Log.i("BatteryLevelReceiver", "Battery Level: " + batteryPct);
      Toast.makeText(getApplicationContext(),"Battery Level:" + batteryPct,Toast.LENGTH_SHORT).show();
     }
    }
   
}

2012年11月8日 星期四

How to get SD Card directory

The official method Environment.getExternalStorageDirectory() seems to be not working for some Phone as this method return primary memory.

“In devices with multiple ‘external’ storage directories (such as both secure app storage and mountable shared storage), this directory represents the ‘primary’ external storage that the user will interact with.”.


Searching in internet and found the following code can find the SD Card directory.

        File file = new File("/system/etc/vold.fstab");
        FileReader fr = null;
        BufferedReader br = null;
        try {
            fr = new FileReader(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        try {
            if (fr != null) {
                br = new BufferedReader(fr);
                String s = br.readLine();
                while (s != null) {
                    if (s.startsWith("dev_mount")) {
                        String[] tokens = s.split("\\s");
                        path = tokens[2]; //mount_point
                        if (!Environment.getExternalStorageDirectory().getAbsolutePath().equals(path)) {
                            break;
                        }
                    }
                    s = br.readLine();
                }
            }           
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fr != null) {
                    fr.close();
                }           
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }