As you know you can name layout or resource folders with “-long” or “-notlong” postfix.
Documentation says:
- long - resources for screens of any size or density that have a significantly taller (in portrait mode) and wider (in landscape mode) aspect ratio than the baseline screen configuration.
- notlong - resources for use only on screens that have an aspect ratio that is similar to the baseline screen configuration.
What does it mean in practice?
hvga – notlong
qvga – notlong
wqvga400 – long
wqvga432 – long
wvga800 – long
wvga854 – long
i.e. if you have aspect ration > 1.5 like 1.78 (480×854) long folders will be used by Android.
For example if you scale layout hvga (1.5) to wvga854 (1.78) – you should take into account additional 480*1.5=720; 854-730=134 pixels in the middle.
p.s. Motorola Flipout is notlong also because it is just landscape qvga.
//DL
What is PhantomReference?
- They allow you to determine exactly when an object was removed from memory. They are in fact the only way to determine that. This isn’t generally that useful, but might come in handy in certain very specific circumstances like manipulating large images: if you know for sure that an image should be garbage collected, you can wait until it actually is before attempting to load the next image, and therefore make the dreaded OutOfMemoryError less likely [read more]
- The main advantage of using a PhantomReference over finalize() is that finalize() is called by a garbage-collector thread, meaning it introduces concurrency even in a single-threaded program, with all the potential issues (like correctly synchronizing shared state). With a PhantomReference, you choose the thread that dequeues references from your queue (in a single-threaded program, that thread could periodically do this job) [read more]
Read more about references here: http://www.ibm.com/developerworks/library/j-refs/
See example in Email application in Android platform: http://google.com/codesearch/p?hl=en#SS2by_AKaLs/src/org/apache/commons/io/FileCleaningTracker.java
Btw, you can also ressurect object with reflection (http://code-o-matic.blogspot.com/2009/01/subtleties-of-phantomreference-and.html)
Here’re small exaple of usage:
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
import java.util.ArrayList;
public class MemoryTest {
private ReferenceQueue<Data> mQueue = new ReferenceQueue<Data>();
private boolean mIsRun = true;
public void test() {
final ArrayList<PhantomReference<Data>> blocks = new ArrayList<PhantomReference<Data>>();
ArrayList<Data> dataArray = new ArrayList<Data>();
System.out.println("occupied mem 1 = " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
for (int i = 0; i < 10; i++) {
Data data = new Data(i);
PhantomReference<Data> ref = new PhantomReference<Data>(data, mQueue);
blocks.add(ref);
dataArray.add(data);
}
System.out.println("occupied mem 2 = " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
System.out.println("remove strong ref to object 0 and 1");
dataArray.remove(0);
dataArray.remove(0);
new Thread() {
public void run() {
System.out.println("thread started");
while (mIsRun) {
Reference<?> ref = null;
try {
ref = mQueue.remove(1000);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
if (ref != null) {
System.out.println(">> removed ref = " + ref);
blocks.remove(ref);
Field f = null;
try {
f = Reference.class.getDeclaredField("referent");
f.setAccessible(true);
System.out.println("I see dead objects! --> " + f.get(ref));
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
System.out.println("thread ended");
}
}.start();
System.out.println("objects created");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("occupied mem 2 = " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
System.out.println("run gc() to make object enqueued");
System.gc();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("collect memory");
System.runFinalization();
System.gc();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("occupied mem 4 = " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()));
mIsRun = false;
}
private static class Data {
int id;
byte[] memoryBlock = new byte[1048576];
public Data(int id) {
this.id = id;
System.out.println("Data created: " + this);
}
@Override
public String toString() {
return "{id=" + id + " " + super.toString() + "}";
}
}
}
What we can see in LogCat:
06-08 14:38:51.154: INFO/System.out(1385): occupied mem 1 = 2186800
06-08 14:38:51.254: DEBUG/dalvikvm(1385): GC freed 845 objects / 56288 bytes in 94ms
06-08 14:38:51.295: INFO/dalvikvm-heap(1385): Grow heap (frag case) to 4.119MB for 1048592-byte allocation
06-08 14:38:51.394: DEBUG/dalvikvm(1385): GC freed 11 objects / 544 bytes in 93ms
06-08 14:38:51.404: INFO/System.out(1385): Data created: {id=0 com.gtug.test.MemoryTest$Data@4373e658}
06-08 14:38:51.484: DEBUG/dalvikvm(1385): GC freed 22 objects / 1456 bytes in 80ms
06-08 14:38:51.534: INFO/dalvikvm-heap(1385): Grow heap (frag case) to 5.119MB for 1048592-byte allocation
06-08 14:38:51.724: DEBUG/dalvikvm(1385): GC freed 159 objects / 7136 bytes in 191ms
06-08 14:38:51.734: INFO/System.out(1385): Data created: {id=1 com.gtug.test.MemoryTest$Data@4372b7e8}
06-08 14:38:51.825: DEBUG/dalvikvm(1385): GC freed 20 objects / 1352 bytes in 92ms
06-08 14:38:51.865: INFO/dalvikvm-heap(1385): Grow heap (frag case) to 6.112MB for 1048592-byte allocation
06-08 14:38:51.965: DEBUG/dalvikvm(1385): GC freed 36 objects / 18336 bytes in 96ms
06-08 14:38:51.974: INFO/System.out(1385): Data created: {id=2 com.gtug.test.MemoryTest$Data@43734338}
06-08 14:38:52.054: DEBUG/dalvikvm(1385): GC freed 20 objects / 1344 bytes in 87ms
06-08 14:38:52.105: INFO/dalvikvm-heap(1385): Grow heap (frag case) to 7.112MB for 1048592-byte allocation
06-08 14:38:52.204: DEBUG/dalvikvm(1385): GC freed 0 objects / 0 bytes in 98ms
06-08 14:38:52.214: INFO/System.out(1385): Data created: {id=3 com.gtug.test.MemoryTest$Data@4372a968}
06-08 14:38:52.285: INFO/System.out(1385): Data created: {id=4 com.gtug.test.MemoryTest$Data@4372a498}
06-08 14:38:52.375: DEBUG/dalvikvm(1385): GC freed 44 objects / 2888 bytes in 92ms
06-08 14:38:52.455: INFO/System.out(1385): Data created: {id=5 com.gtug.test.MemoryTest$Data@43736180}
06-08 14:38:52.565: DEBUG/dalvikvm(1385): GC freed 25 objects / 1464 bytes in 102ms
06-08 14:38:52.635: INFO/System.out(1385): Data created: {id=6 com.gtug.test.MemoryTest$Data@4372b950}
06-08 14:38:52.755: DEBUG/dalvikvm(1385): GC freed 28 objects / 1584 bytes in 116ms
06-08 14:38:52.804: INFO/ActivityManager(578): Displayed activity com.gtug.test/.PhantomTest: 2327 ms
06-08 14:38:52.875: INFO/System.out(1385): Data created: {id=7 com.gtug.test.MemoryTest$Data@4373b680}
06-08 14:38:53.065: DEBUG/dalvikvm(1385): GC freed 26 objects / 1600 bytes in 179ms
06-08 14:38:53.104: INFO/System.out(1385): Data created: {id=8 com.gtug.test.MemoryTest$Data@437381a8}
06-08 14:38:53.185: DEBUG/dalvikvm(1385): GC freed 24 objects / 1504 bytes in 74ms
06-08 14:38:53.224: INFO/System.out(1385): Data created: {id=9 com.gtug.test.MemoryTest$Data@4373aec8}
06-08 14:38:53.235: INFO/System.out(1385): occupied mem 2 = 12600240
06-08 14:38:53.235: INFO/System.out(1385): remove strong ref to object 0 and 1
06-08 14:38:53.244: INFO/System.out(1385): thread started
06-08 14:38:53.244: INFO/System.out(1385): objects created
06-08 14:38:56.254: INFO/System.out(1385): run gc() -> overrided finalyze print
06-08 14:38:56.324: DEBUG/dalvikvm(1385): GC freed 45 objects / 2512 bytes in 74ms
06-08 14:38:56.334: INFO/System.out(1385): Data finalized: {id=1 com.gtug.test.MemoryTest$Data@4372b7e8}
06-08 14:38:56.334: INFO/System.out(1385): Data finalized: {id=0 com.gtug.test.MemoryTest$Data@4373e658}
06-08 14:38:58.184: DEBUG/dalvikvm(622): GC freed 119 objects / 5872 bytes in 79ms
06-08 14:38:59.344: INFO/System.out(1385): occupied mem 3 = 12602504
06-08 14:38:59.344: INFO/System.out(1385): run gc() second time to make object enqueued
06-08 14:38:59.434: DEBUG/dalvikvm(1385): GC freed 45 objects / 2944 bytes in 85ms
06-08 14:38:59.434: INFO/System.out(1385): >> removed ref = java.lang.ref.PhantomReference@4373a4c0
06-08 14:38:59.434: INFO/System.out(1385): I see dead objects! --> {id=1 com.gtug.test.MemoryTest$Data@4372b7e8}
06-08 14:38:59.434: INFO/System.out(1385): >> removed ref = java.lang.ref.PhantomReference@437343f8
06-08 14:38:59.434: INFO/System.out(1385): I see dead objects! --> {id=0 com.gtug.test.MemoryTest$Data@4373e658}
06-08 14:39:02.446: INFO/System.out(1385): collect memory
06-08 14:39:02.524: DEBUG/dalvikvm(1385): GC freed 75 objects / 2101968 bytes in 76ms
06-08 14:39:07.554: INFO/System.out(1385): occupied mem 4 = 10503728
06-08 14:39:08.454: INFO/System.out(1385): thread ended<!--more-->
happy coding!
//DL
It was reported by Phandroid that all or some of HTC Legend and Desire Android smartphones have poor grayscale reproduction.

Now you can quick check your HTC device does it have this grayscale issue or not using small tool from Android Market – Screen Test.
Originally application was created to help in dead pixels finding. Current release has some extra useful screens to test your device and now includes grayscale gradient to be sure that your HTC Legend or Desire phone is fine.
You can download application from Android Market by searching “Screen Test” or just scan QR-code below.

And don’t forget to comment on this or original Phandroid post to clarify is this is the issue for all HTC Legend phones or not.
June 3rd,2010
HTC,
android,
device,
hardware | tags:
AMOLED,
android,
grayscale issue,
grayscale reproduction,
HTC,
HTC Desire,
HTC Legend,
screen,
ScreenTest |
No Comments
It’s just great! Share passion to the Droids:)
source: http://vkontakte.ru/album-15955496_105624045
In our application we need to apply mask to some icons to make them semitransparent. The original images are in RGB format i.e. without alpha channel. To apply mask we need add alpha channel to original images. Before Android 2.0 we did this like:
Bitmap dest = src.copy(Bitmap.Config.ARGB_8888, true);
When we run our application on Android 2.1 device we noticed that the destination bitmap is created but without alpha channel. After applying mask, pixels that should be semitransparent become black.
The getPixel() method returns different value than was set by setPixel() method.
So, how to add alpha channel to RGB bitmap?
There are three ways:
First:
Use ARGB_4444 format:
Bitmap dest = src.copy(Bitmap.Config.ARGB_4444, true);
In this case the alpha channel will be added, but you will lose the quality of image
Second:
Create empty bitmap with dimensions of original image and ARGB_8888 format:
int width = src.getWidth();
int height = src.getHeight();
Bitmap dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Copy pixels from source bitmap to the int array:
int[] pixels = new int[width * height];
src.getPixels(pixels, 0, width, 0, 0, width, height);
And set these pixels to destination bitmap:
dest.setPixels(pixels, 0, width, 0, 0, width, height);
The alpha channel will be added without losing image quality. But this way is too slow ~ 5027ms average for 1000 bitmaps
Third: (Thanks to Cyril Mottier post)
First of all you need to create mask image which you want to apply to the icon and put it in to the resources.
Then you need to create Paint object and set xfermode to it:
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
And draw source bitmap and mask on canvas:
canvas.drawBitmap(src, 0, 0, null);
canvas.drawBitmap(icon, 0, 0, paint);
This way requires to have mask image (you can’t modify source bitmap on the fly), but it is fast (~ 2659ms average for 1000 bitmaps) and without quality loss
Found today a post
- Go to phone app
- Dial *#*#4636#*#*
- See secret test menu:)

I’ve looked deep into platform code. Here’s are the code from Phone.git
static boolean handleSecretCode(Context context, String input) {
// Secret codes are in the form *#*#<code>#*#*
int len = input.length();
if (len > 8 && input.startsWith("*#*#") && input.endsWith("#*#*")) {
Intent intent = new Intent(Intents.SECRET_CODE_ACTION,
Uri.parse("android_secret_code://" + input.substring(4, len - 4)));
context.sendBroadcast(intent);
return true;
}
return false;
}
So, let’s search for Intent filters:
Settings.git
<receiver android:name="TestingSettingsBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data android:scheme="android_secret_code" android:host="4636" />
</intent-filter>
</receiver>
CalendarProvider.git (this one works only on >2.0)
<receiver android:name="TestingSettingsBroadcastReceiver">
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data android:scheme="android_secret_code" android:host="225" />
</intent-filter>
</receiver>
VoiceDialer.git
<!-- Voice Dialer Logging Enabled, *#*#VDL1#*#* -->
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data android:scheme="android_secret_code" android:host="8351" />
</intent-filter>
<!-- Voice Dialer Logging Disabled, *#*#VDL0#*#* -->
<intent-filter>
<action android:name="android.provider.Telephony.SECRET_CODE" />
<data android:scheme="android_secret_code" android:host="8350" />
</intent-filter>
You can add your own codes!:)
//DL
It’s relatively easy to add headset button support to your application. For example you want to play/pause media playback in your super media player.
But here are a few moments that you should take into consideration:
- You should register your broadcast receiver inside your application (not in manifest file). Otherwise Google Music player will catch your broadcast and aboard it. http://android.git.kernel.org/?p=platform/packages/apps/Music.git;a=blob;f=src/com/android/music/MediaButtonIntentReceiver.java
- Your IntentFilter priority should be higher that other media players priorities in your phone:) That’s kind of tricky thing.
The code snippet will look like:
MediaButtonIntentReceiver mMediaButtonReceiver = new MediaButtonIntentReceiver();
IntentFilter mediaFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
mediaFilter.setPriority(MEDIA_BUTTON_INTENT_EMPIRICAL_PRIORITY_VALUE);
registerReceiver(mMediaButtonReceiver, mediaFilter);
And MediaButtonIntentReceiver.java
public class MediaButtonIntentReceiver extends BroadcastReceiver {
public MediaButtonIntentReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
String intentAction = intent.getAction();
if (!Intent.ACTION_MEDIA_BUTTON.equals(intentAction)) {
return;
}
KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (event == null) {
return;
}
int action = event.getAction();
if (action == KeyEvent.ACTION_DOWN) {
// do something
}
abortBroadcast();
}
}
- Don’t forget to unregister your broadcast receiver
- Add “android.permission.BLUETOOTH” permission if you want to support bluetooth headset
// DL
We decided to try some analytic tool to compare it with Flurry analytics (http://www.flurry.com/) that we currently use in our applications. Our choice has fallen on Motally Mobile Analytics (http://www.motally.com).
After signing up to Mottaly, we add our application and got an “Application Key” which should be used within the API initialization. Then we download motally library and API documentation and started to integrate Motally into our application…
First of all we read the API documentation (http://motally.com/api/motally_android_api_doc.pdf) and tried the example from this document. And we were surprised that our code is not compiled because some methods cannot be found. Our next step was motally javadoc studying. We have found out that javadoc and API documentation have a lot of differences. For example API documentation says:
“Every Activity or Service within your application must retrieve the MoTrack object in order to invoke tracking calls on it. This is done with the help of the getSharedTracker method.”
But, there are no getSharedTracker() method in the motally library. And all methods are static and non of them do not return instance of Motrack object.
So, motally API Documentation is absolutely useless as does not coincide with the latest motally library for Android.
Eventually, using javadoc we have integrated motally analytics into our application, but… In the sniffer log of our applications we did not see any posts made by motally API.
To understand how motally works we … decompiled there code
All motally API methods are static in MoTracker class that extends android.app.Service.
To start tracking you need to start initSharedTracker() method, which init some preferences (such as Application Key) and starts Motally Service.
MoTracker object is initializing in onStartCommand() method which is called by the system every time a client explicitly starts the service.
But onStartCommand() method is available only since Android API level 5. Before Android API level 5 the onStart() method were used. Because of that Motally does not work on Android 1.5 and 1.6 devices.
Thus having tried Motally Mobile Analytics we decided to stay with Flurry
Bada… in short
- no multitask for user’s apps
- no background services for user’s apps. only push notification from Bada server
- Bada social hub (twitter, facebook, myspace)
- 1GHz
- C++ development (Eclipse plug-in) – only for Windows
- 7-days mandatory app review to sell your app (Samsung app store)
- DRM application protection
- Billing integration with i-Free in Russia
- Global developers chalenge (2.7M$) Mar 16 – Aug 15 ’2010
and the first Bada phone (Samsung Wave)… for the price of Nexus One

Samsung Wave (Bada)
//DL