Android – get DIP with Java
Here's a little class to get density-independent pixels, and pixels from DIP:
package org.upshots.utils;
import android.content.Context;
public class DensityManager {
private static DensityManager instance = null;
public static DensityManager getInstance(Context context){
if(instance == null){
instance = new DensityManager(context);
}
return instance;
}
private float scale = 1f;
private DensityManager(Context context){
scale = context.getResources().getDisplayMetrics().density;
}
public int DIPToPixels(float dip){
return (int) (0.5 + (dip * scale));
}
public int DIPToPixels(int dip){
return DIPToPixels((float) dip);
}
public int DIPToPixels(double dip){
return DIPToPixels((float) dip);
}
public int pixelsToDIP(float pixels){
return (int) (0.5 + (pixels / scale));
}
public int pixelsToDIP(int pixels){
return pixelsToDIP((float) pixels);
}
public int pixelsToDIP(double pixels){
return pixelsToDIP((float) pixels);
}
}
usage...
// argument 'context' would be 'this' from an Activity // or getContext() from a view DensityManager.getInstance(context).pixelsFromDIP(100); // or... DensityManager.getInstance(context).DIPFromPixels(100);
MySQL – get most frequent values
here's a little query that'll return the 10 most common values for any particular field in a MySQL table.
SELECT <column>, COUNT(<column>) AS popularity FROM <table> GROUP BY <column> ORDER BY popularity DESC limit 10;
Android – set alpha (opacity) for a custom view
While API 3.0 has a setAlpha method, most of us are still targeting 2.x since penetration for anything over 2.2 is pretty slim.
ImageViews and Drawables already have setAlpha methods, and TextViews can be manipulated using various ARGB colors. Some people just use zero-duration AlphaAnimations, so generally you can get the effect you need, but sometimes you'll need a little more complex behavior (e.g., setting opacity based on drag position) or convenient (e.g., setting the alpha of the contents an entire layout).
Fortunately, it's pretty simple - despite the lack of documentation.
Just extend your Layout and override onDraw, and use the canvas's setLayerAlpha method:
@Override
public void onDraw(Canvas canvas){
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), 0x66, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
super.onDraw(canvas);
}
Extended to support method calls:
package org.upshots.widgets;
import android.content.Context;
import android.graphics.Canvas;
import android.widget.RelativeLayout;
public class FadingLayout extends RelativeLayout {
private int alpha = 255;
public FadingLayout(Context context) {
super(context);
setWillNotDraw(false);
}
public int getAlpha(){
return alpha;
}
public void setAlpha(int opacity){
alpha = opacity;
invalidate();
}
@Override
public void onDraw(Canvas canvas){
canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), alpha, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
super.onDraw(canvas);
}
}
Android – get dimensions of image resource
Context context = // "this" if from an Activity, or "getContext()" if from a View Resources resources = context.getResources(); BitmapFactory.Options bounds = new BitmapFactory.Options(); bounds.inJustDecodeBounds = true; // resId below might be something like R.drawable.my_image BitmapFactory.decodeResource(resources, resId, bounds); int imageHeight = bounds.outHeight; int imageWidth = bounds.outWidth;
Android – remove title and status bars from your app
In your manifest XML, add this property to your application node:
<application android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
Android – WindowManager for overlays
Several core classes (including Dialog, PopupWindow and some Menu implementations) create an "overlay layer" that exists above, and separate from, existing UI elements - this is why we don't need to use special layoutmanagers on underlying Activity contentViews in order to position them. While the documentation is sparse, and cloning those classes is challenging (due to the inaccessible com.android.internal classes like PolicyManager), it's actually fairly simple to implement the functionality.
Use WindowManager.addView(view, windowManagerLayoutParams) to add a new layer. E.g., to add a view glued to the bottom of the screen, that'll overlay existing content:
WindowManager.LayoutParams wlp = new WindowManager.LayoutParams();
wlp.gravity = Gravity.BOTTOM;
wlp.height = WindowManager.LayoutParams.WRAP_CONTENT;
wlp.width = WindowManager.LayoutParams.FILL_PARENT;
wlp.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
wlp.format = PixelFormat.RGBA_8888;
WindowManager wm = (WindowManager) getSystemService("window");
wm.addView(someView, wlp);
You can supply animation resources to the WindowManager.LayoutParams instance, but AFAICT there is no way to add or use programmatic animation to either the window or any of it's content children.
jQuery – remove attributes
a little jQuery extension that removes multiple attributes, with white- and black-lists.
the first argument is a list of attributes to remove. if omitted, it removes all attributes on the element, except those in the second argument. both are arrays of strings.
$.fn.removeAttributes = function(only, except) {
if (only) {
only = $.map(only, function(item) {
return item.toString().toLowerCase();
});
};
if (except) {
except = $.map(except, function(item) {
return item.toString().toLowerCase();
});
if (only) {
only = $.grep(only, function(item, index) {
return $.inArray(item, except) == -1;
});
};
};
return this.each(function() {
var attributes;
if(!only){
attributes = $.map(this.attributes, function(item) {
return item.name.toString().toLowerCase();
});
if (except) {
attributes = $.grep(attributes, function(item, index) {
return $.inArray(item, except) == -1;
});
};
} else {
attributes = only;
}
var handle = $(this);
$.each(attributes, function(index, item) {
handle.removeAttr(item);
});
});
};
Usage...
$('#bob').removeAttributes(['id', 'class']); // remove id and class attributes
$('#bob').removeAttributes(null, ['href']); // remove all attributes except href
This can actually be a handy function for sanitizing HTML input, for example in a Rich Text Editor where you want to allow pastes from Word or dragging HTML content into a contentEditable div - pass the html() to a temp div, removeAttributes on all elements, then pass it to your DB.
HTH.
CodeIgniter – AJAX + Session bug fix
If you've used AJAX-heavy web apps built on a CI backend, you might have noticed premature session expiration, even if you're expiration was set to never expire ($config['sess_expiration'] = 0; in application/config/config.php)
This was apparently due to AJAX requests not regenerating sessions, and apparent collisions. Long story short, last month there was a patch introduced without much fanfare, which (so far) seems to be working for me.
Replace your system/libraries/Session.php file with the one found here (CI's git):
Android – Java for unique collection
In Java, there are several collections we can use for a variety of tasks - normally when we want a unique list, we should use a Set or a Set subclass. However, there are times when we want to unique-ify a different type of Collection (like an ArrayList). A simple way to do that is to create a HashSet (or a LinkedHashSet if you want to preserver the order of indexes), then pass the original Collection to the HashSet's addAll method, clear the original Collection, then pass the HashSet to the original Collection's addAll method... E.g.,
ArrayList<Integer> numbers = new ArrayList<Integer>(); numbers.add(1); numbers.add(2); numbers.add(3); numbers.add(3); numbers.add(3); LinkedHashSet<Integer> unique = new LinkedHashSet<Integer>(); unique.addAll(numbers); numbers.clear(); numbers.addAll(unique); // now numbers will contain: 1, 2, 3
Handling Android emulator errors
When I first started with Android development, I tried use the built-in emulator and was shocked by how long it took to launch (anywhere from 4 to 10 minutes on my laptop). Crawling the boards it became obvious this was a common issue and that most developers used real devices - I followed suit and we've been happily debugging on a Samsung Galaxy SII and a Nexus One ever since.
Today, before an early release, we wanted to test it on some other configurations, so I fired up AVD. 3 hours (and a lot of red console messages) later, here's what I learned:
The first error was:
"Failed to install blah.apk on device 'emulator-5554': timeout"
Fix: (from Eclipse) Window > Preferences > Android > DDMS > ADB Timeout something... Increased that from 5000 (default) to 10000
Ran again. Got this:
Failed to install blah.apk on device 'emulator-5554': No space left on device
Fix: (from Eclipse) Window > AVD Manager > <select device> increase SD Car size to 500MB. In same window, in a little table under "Hardware", change "Max VM Application Heap Size" to 100.
Ran again. More red:
Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE
Fix: (from Eclipse) click the drop-down arrow to the right of the "Run" icon. Select "Run Configurations". Click the "Target" tab. Check the virtual device you want to use. In the same window, there's an area called "Emulator Launch Parameters" - this does not have a scrollbar, but there is overflow content - I just got lucky and guessed, and by resizing the window I saw an input box labelled "Additional Emulator Command Line Options" - put the following line in that box: "-partition-size 1024" (omit the quotes).
Now, as long as you launch the emulator from the Run icon (so it considers the options supplied above), you'll have probably a better than even chance of getting your application to run. If you end up staring at a lock icon on your emulator screen for 15-20 minutes like I did, use you mouse to drag the lock to the right to open the device and see your app.