How to get a File object of an Android raw resource using reflection

Context:

You have a URI to a resource which is placed in the raw directory inside the Android resources directory, res.¬†Say you want to take that raw resource(let’s say it’s an image) and add it to an attachment using FIleBody to a MultiPartEntity. Both these classes are available in the Apache HTTP Components library. FileBody will only allow you to give it a File object¬†in it’s constructor. Certainly, you are stuck as you have the URI to an Android raw resource, and CANNOT create a File object out of it.

 

So what’s the solution? Reflection.

    private File getFileFromRawResource(Uri rUri) {
        String uri = rUri.toString();
        String fn;
        // I've only tested this with raw resources
        if (uri.contains("/raw/")) {
            // Try to get the resource name
            String[] parts = uri.split("/");
            fn = parts[parts.length - 1];
        } else {
            return null;
        }
        // Notice that I've hard-coded the file extension to .jpg
        // I was working with getting a File object of a JPEG image from my raw resources
        String dest = Environment.getExternalStorageDirectory() + "/image.jpg";
        try {
            // Use reflection to get resource ID of the raw resource
            // as we need to get an InputStream to it
            // getResources(),openRawResource() takes only a resource ID
            R.raw r = new R.raw();
            Field frame = R.raw.class.getDeclaredField(fn);
            frame.setAccessible(true);
            int id = (Integer) frame.get(r);
            // Get the InputStream
            InputStream inputStream = getResources().openRawResource(id);
            FileOutputStream fileOutputStream = new FileOutputStream(dest);
            // IOUtils is a class from Apache Commons IO
            // It writes an InputStream to an OutputStream
            IOUtils.copy(inputStream, fileOutputStream);
            fileOutputStream.close();
            return new File(dest);
        } catch (NoSuchFieldException e) {
            Log.e("MyApp", "NoSuchFieldException in getFileFromRawResource()");
        } catch (IllegalAccessException e) {
            Log.e("MyApp", "IllegalAccessException in getFileFromRawResource()");
        } catch (FileNotFoundException e) {
            Log.e("MyApp", "FileNotFoundException in getFileFromRawResource()");
        } catch (IOException e) {
            Log.e("MyApp", "IOException in getFileFromRawResource()");
        }
        return null;
    }    

The code is pretty much self-explanatory. Drop a comment if you have any questions/doubts.

Calculate the REAL scale factor and the angle of rotation from an Android Matrix

After performing transformations such as rotation of a bitmap about an arbitrary point, the scale is lost. Of course, this makes sense because the bitmap is rotated inside the same bounds.

To get the real scale now, along with the most reliable degree of rotation, I had to follow this method. Hope it saves the rest of you a night or two.

float[] v = new float[9];
matrix.getValues(v);
// translation is simple
float tx = v[Matrix.MTRANS_X];
float ty = v[Matrix.MTRANS_Y];

// calculate real scale
float scalex = values[Matrix.MSCALE_X];
float skewy = values[Matrix.MSKEW_Y];
float rScale = (float) Math.sqrt(scalex * scalex + skewy * skewy);

// calculate the degree of rotation
float rAngle = Math.round(Math.atan2(v[Matrix.MSKEW_X], v[Matrix.MSCALE_X]) * (180 / Math.PI));

Multi Touch in Android – Translate, Scale, and Rotate

Here’s a quick and easy implementation of Android’s multi touch feature – one finger to move, two to zoom, and three to rotate the image.

Assuming you have a basic understanding of 2D matrix transformations, the Matrix class in Android uses a 3×3 matrix to achieve all of the 2D transformations.

The source code and pre -built APK is available. See the end of this post.

Main activity – MultiTouch.java

package com.multitouch.example;

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class MultiTouch extends Activity implements OnTouchListener {

    // these matrices will be used to move and zoom image
    private Matrix matrix = new Matrix();
    private Matrix savedMatrix = new Matrix();
    // we can be in one of these 3 states
    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    // remember some things for zooming
    private PointF start = new PointF();
    private PointF mid = new PointF();
    private float oldDist = 1f;
    private float d = 0f;
    private float newRot = 0f;
    private float[] lastEvent = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ImageView view = (ImageView) findViewById(R.id.imageView);
        view.setOnTouchListener(this);
    }

    public boolean onTouch(View v, MotionEvent event) {
        // handle touch events here
        ImageView view = (ImageView) v;
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                savedMatrix.set(matrix);
                start.set(event.getX(), event.getY());
                mode = DRAG;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                oldDist = spacing(event);
                if (oldDist > 10f) {
                    savedMatrix.set(matrix);
                    midPoint(mid, event);
                    mode = ZOOM;
                }
                lastEvent = new float[4];
                lastEvent[0] = event.getX(0);
                lastEvent[1] = event.getX(1);
                lastEvent[2] = event.getY(0);
                lastEvent[3] = event.getY(1);
                d = rotation(event);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                lastEvent = null;
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == DRAG) {
                    matrix.set(savedMatrix);
                    float dx = event.getX() - start.x;
                    float dy = event.getY() - start.y;
                    matrix.postTranslate(dx, dy);
                } else if (mode == ZOOM) {
                    float newDist = spacing(event);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = (newDist / oldDist);
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                    if (lastEvent != null && event.getPointerCount() == 3) {
                        newRot = rotation(event);
                        float r = newRot - d;
                        float[] values = new float[9];
                        matrix.getValues(values);
                        float tx = values[2];
                        float ty = values[5];
                        float sx = values[0];
                        float xc = (view.getWidth() / 2) * sx;
                        float yc = (view.getHeight() / 2) * sx;
                        matrix.postRotate(r, tx + xc, ty + yc);
                    }
                }
                break;
        }

        view.setImageMatrix(matrix);
        return true;
    }

    /**
     * Determine the space between the first two fingers
     */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /**
     * Calculate the mid point of the first two fingers
     */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

    /**
     * Calculate the degree to be rotated by.
     *
     * @param event
     * @return Degrees
     */
    private float rotation(MotionEvent event) {
        double delta_x = (event.getX(0) - event.getX(1));
        double delta_y = (event.getY(0) - event.getY(1));
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }
}

An important function that is always used is postXx(). This function concats a new matrix of the type Xx to the existing matrix object. Using setXx() will reset the matrix’s Xx property.
Main layout – main.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ImageView android:id="@+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/butterfly"
android:scaleType="matrix" />

</FrameLayout>

Browse and download the source code on GitHub.

Rooted? Get the most of your Android phone | A power saving strategy

The smart-phones these days are power hungry devices, and often drain the battery within six to eight hours, or even less. However, if it’s running Android, there’s a good chance that that can change. The key is to find the right set of tools, and optimize your phone to be right on the edge, there when you need it, and highly responsive. What it takes is a power saving strategy, offered by Set CPU for root users android application. This nifty little tool, worth it’s price, is by far the most essential application among several others(probably thousands). It allows you to set profiles, and depending on how well you set it up, you can extend your battery life by a couple of hours(~four).
So how do you balance phone responsiveness while saving power at the same time?
Take a look at the following two screenshots, it’s what I’ve got setup:

The settings indicated above, automatically scale the CPU frequency. The highest CPU frequency supported by your processor will take the most power, so if you’d want to scale it down, especially during low levels of battery, this application can help you do so automatically.
Read about the profile priority when setting up newer profiles for this application.

You can read about which CPU frequency governor is right for you here