Monday, December 24, 2012

Android BroadcastReceiver is not working after install ? How to fix this ?

Starting from Android 3.1 after you install an application all broadcast receivers are in "STOPPED" state until you click on the icon and start the application. I wanted dig-in to find a solution for this problem. This is what I discovered under the hood.

 com.android.server.pm.Settings.readStoppedLPw() is invoked on BOOT_COMPLETE and it checks for


String tagName = parser.getName();
if (tagName.equals("pkg")) {
    String name = parser.getAttributeValue(null, "name");
    PackageSetting ps = mPackages.get(name);
    if (ps != null) {
        ps.stopped = true;
        if ("1".equals(parser.getAttributeValue(null, "nl"))) {
            ps.notLaunched = true;
        }
    } else {
        Slog.w(PackageManagerService.TAG, "No package known for stopped package: " + name);
    }
so, what is this "nl" ? When you install an apk, your broadcast receiver will listed on /data/system/packages-stopped.xml 


<stopped-packages>
<pkg name="test.broadcast" nl="1" />
</stopped-packages>

So, If you want to enable your packages back, you must modify this file and push it back to /data/system/packages-stopped.xml  with nl="0" 

to get it to work.

and then rebroadcast the BOOT_COMPLETED and you should be fine

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

to do all these you must have root. otherwise no choice

Wednesday, October 3, 2012

How to get all installed SD cards on Android

Today, I wanted to get all installed SD Cards on the device. In Android you can use Environment.getExternalStorageDirectory() get the  external device path but if you have more than 1, (in Galaxy S3 it has 2) you are in trouble. After few hours of Googling i managed to put this code together and hope it will help someone else too..

private static ArrayList<String> mMounts = new ArrayList<String>();
private void dumpAllSDCards() {
mMounts.add("/mnt/sdcard");
     
        try {
            Scanner scanner = new Scanner(new File("/proc/mounts"));
            while (scanner.hasNext()) {
              String line = scanner.nextLine();
              if (line.startsWith("/dev/block/vold/")) {
                String[] lineElements = line.split(" ");
lineElements[1].replaceAll(":.*$", "");
String element = lineElements[1];
                if (!element.equals("/mnt/sdcard")) mMounts.add(element);
              }
            }
          } catch (Exception e) {
           Log.d("MainActivity", e.toString());
          }
     
        for (int i = 0; i < mMounts.size(); i++) {
String mount = mMounts.get(i);
File root = new File(mount);
if (!root.exists() || !root.isDirectory() || !root.canWrite())
mMounts.remove(i--);
}
     

        for (String drive : mMounts) {
Log.d("MainActivity", drive + " exist!");
}     
}

Thursday, September 27, 2012

How to create a thumbnail from a video in Android


/**
     * Create a video thumbnail for a video. May return null if the video is
     * corrupt or the format is not supported.
     *
     * @param filePath the path of video file
     * @param kind could be MINI_KIND or MICRO_KIND
     */
    public static Bitmap createVideoThumbnail(String filePath, int kind) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(filePath);
            bitmap = retriever.getFrameAtTime(-1);
        } catch (IllegalArgumentException ex) {
            // Assume this is a corrupt video file
        } catch (RuntimeException ex) {
            // Assume this is a corrupt video file.
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
                // Ignore failures while cleaning up.
            }
        }

        if (bitmap == null) return null;

        if (kind == Images.Thumbnails.MINI_KIND) {
            // Scale down the bitmap if it's too large.
            int width = bitmap.getWidth();
            int height = bitmap.getHeight();
            int max = Math.max(width, height);
            if (max > 512) {
                float scale = 512f / max;
                int w = Math.round(scale * width);
                int h = Math.round(scale * height);
                bitmap = Bitmap.createScaledBitmap(bitmap, w, h, true);
            }
        } else if (kind == Images.Thumbnails.MICRO_KIND) {
            bitmap = extractThumbnail(bitmap,
                    TARGET_SIZE_MICRO_THUMBNAIL,
                    TARGET_SIZE_MICRO_THUMBNAIL,
                    OPTIONS_RECYCLE_INPUT);
        }
        return bitmap;
    }

Sunday, September 9, 2012

How to use SQL LIKE with content uri?

Today, I wanted to look something up from the Android calendar using URI. Its simple

String where = "title LIKE '%"+ searchText +"%'";

String[] projection = new String[] { "_id", "title", "description", "dtstart", "eventLocation" };
Cursor cursor = context.getContentResolver().query(
Uri.parse(getCalendarUriBase()), projection, where, null, null);

Don't use Selection and SelectionArgs. It does not work

Monday, August 13, 2012

Adapter pattern explained in real life example

Today, I was going through one of the projects in Google code repository and I found this. After reading this only even I understood whats the Adapter pattern is about :)


/**
 * If you don't know about "Adapter", let me explain it in a short example:
 * You are a girl and you have to sit during the time taking a piss.
 * I am a boy and I can stand straight while taking a piss.
*
 *If you have water-spout in your hands, you can stand upright to have a  piss =))
 * And from that point, you would have known: Yes, water-spout is an Adapter
 *
 * Just joking, forget it! Google Apdater design patterns =))
*/

Wednesday, June 20, 2012

android::CameraHardwareSec::takePicture() : capture already in progress error

Today, One of the Android devices keep getting crashed while taking a picture in a TimerTask. I was keep getting this error


E/CameraHardwareSec(75): virtual android::status_t android::CameraHardwareSec::takePicture() : capture already in progress
E/PanicImageActivity(1750): java.lang.RuntimeException: takePicture failed


problem is before you call this method again in the TimerTask run method. you need to make sure that there is one not in progress. Some devices cameras are very slow on processing picture frames.


private final Semaphore mutex = new Semaphore(1);



try {

mutex.acquire();


mCamera.takePicture(null, null, new PictureCallback() { 
        public void onPictureTaken(byte[] data, Camera camera) {
try {
             // Do something here
              mutex.release();
         }

         catch(Throwable t) {
          mutex.release();
         }

});
}
catch (Throwable t) {

 }

Tuesday, June 19, 2012

How to check whether Android Media Scanner is running ?

Here is the code


    public static final boolean isMediaScannerScanning(final ContentResolver cr) {
        boolean result = false;
        final Cursor cursor = query(cr, MediaStore.getMediaScannerUri(), new String[] { MediaStore.MEDIA_SCANNER_VOLUME }, null,
                null, null);
        if (cursor != null) {
            if (cursor.getCount() == 1) {
                cursor.moveToFirst();
                result = "external".equals(cursor.getString(0));
            }
            cursor.close();
        }
        return result;
    }