Friday, April 4, 2014

Sending touch event to the android device by using monkeyrunner



Using the monkeyrunner, you can control the device with connected on a pc.
It is contained in the android sdk from google.

http://developer.android.com/tools/help/monkeyrunner_concepts.html


Preparation

  1. Install android sdk (recent version, maybe?)
  2. Turn on the debugging option of the device

  3. If DOWN_AND_UP is not working well,
    Settings >  Pointer speed > Lower the speed


Write following python for the first try.

# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()
# Presses the Menu button
device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP)
# Touches (x, y) position
device.touch(x, y, MonkeyDevice.DOWN_AND_UP)

Connect your device to your pc, confirm it is well being debugging.
Type the following script.
$ adb devices

If it is well connected, it will reply device's some string.

To confirm that the touch is working well, I suggest you run some paint app first such as Sketchbook express, Evernote skitch.

With the device connected to the pc, run monkeyrunner with your python script.

<android sdk directory>/tools/monkeyrunner <your script>.py

(x, y) position is dependent on your device's resolution (pixel coordination).
(500, 500) is ok, I think.

If you want to know exact position of the device, turn some settings on.

  1. Developer options > Input > Show touches CHECK
  2. Developer options > Input > Pointer location CHECK
With this setting, you can check the exact coordinate of the location when you touch somewhere.
Location will be shown on the top of the screen.














Sunday, March 9, 2014

Parse.com android push notifications


It seems to work for sending simple pushes to both android, ios devices.
Installation special object seems to be used to send a certain segment of devices.

https://parse.com/tutorials/android-push-notifications

The Parse library provides push notifications by using Google Cloud Messaging (GCM) if possible. On devices that do not support GCM (such as the Amazon Kindle Fire), Parse will use a background service that maintains a persistent connection to the Parse Cloud to deliver pushes. This allows Parse Push to work on all devices running Android 2.2 or higher.


Some push features are available only for pro users.


Global Push opens metrics Visualize how often your app is opened because of a push notification you sent.
Advanced Push Targeting Ability to perform advanced targeting in the Parse Push console.
Push Scheduling Ability to schedule pushes in the Parse Push console.


Thursday, February 6, 2014

multithreading MessagePack usage without java PermGen memory error


If you use new MessagePack() too many time, perm gem memory error occurs soon.

MessagePack msgpack = new MessagePack();
byte[] bytes = msgpack.write(object);

You can test this with
-XX:+TraceClassLoading -XX:+TraceClassUnloading
VM parameters or JConsole.

[Loaded learningtest.msgpack.MessagePackTest$MyMessage_$$_Template_1527741453_0 from __JVM_DefineClass__]
MyMessage [name=msgpack, version=0.6]
[Loaded learningtest.msgpack.MessagePackTest$MyMessage_$$_Template_831556519_0 from __JVM_DefineClass__]
MyMessage [name=msgpack, version=0.6]
[Loaded learningtest.msgpack.MessagePackTest$MyMessage_$$_Template_1872305359_0 from __JVM_DefineClass__]
MyMessage [name=msgpack, version=0.6]

MessagePack.write()
TemplateRegistry.lookup()
TemplateRegistry.lookupAfterBuilding()
TemplateRegistry.buildAndRegister()
AbstractTemplateBuilder.buildTemplate()
DefaultBuildContext.buildTemplate()
BuildContext.build()
BuildContext.createClass()
CtClass.toClass()


But, writing with the MessagePack instance is not thread-safe.
msgpack.setOutputStream(outputStream);
msgpack.write(object);

Insteads, you can should the packer and the unpacker from a singleton MessagePack instance

MessagePack msgpack = new MessagePack(); // singleton
Packer packer = msgpack.createPacker(outputStream); // createPacker every time
packer.write(object);

for (int i = 0; i < 100; i++) {
final int iTask = i;
tasks.add(new Thread() {

@Override
public void run() {
try {
System.out.println(iTask + " start ");
File file = new File("eraseme" + iTask);
FileOutputStream outputStream = null;

outputStream = new FileOutputStream(file);
SomeClass info = new SomeClass();
try {
packer.write(info);
catch (IOException e) {
System.out.println(iTask + " write failed " + e.getMessage());
assertTrue(false);
}
outputStream.close();
FileInputStream inputStream = new FileInputStream(file);
Unpacker unpacker = msgpack.createUnpacker(inputStream);
// Deserialize directly using a template
SomeClass reply = null;
try {
reply = (ReplyMessage.ImageInfoMessage) unpacker.read(SomeClass.class);
catch (IOException e) {
System.out.println(iTask + " read failed " + e.getMessage());
assertTrue(false);
}
System.out.println(iTask + " finished " + reply + " " + file.getAbsolutePath());
catch (Exception exc) {
System.out.println("exc " + exc.getMessage());
assertTrue(false);
}
};
});
}
for (Thread task : tasks) {
task.start();
}
for (Thread task : tasks) {
task.join();
}

assertTrue(true);


Or, we should use pool of MessagePack instances.
I suggest the apache commons pool.
http://commons.apache.org/proper/commons-pool/



Friday, December 20, 2013

To stop animator determitively, nineoldandroid's Animator.end() is not enough.




Requirements

  1. Animators sometimes should be stopped onPause
  2. The status of properties that animators have been changing should be known to us (activity(?)). It should be determinable.


I wanted to pause animators. And, I used the nineoldandroids for the back compatibility.

If you cancel the animator, you may not be sure that the properties of View are changed for which amount.
This often yields various bugs.

voidcancel()
Cancels the animation.

So, I wanted to

voidend()
Ends the animation.Note that ending a AnimatorSet also ends all of the animations that it is responsible for.


I tried calling animator.end() by hand, but, property value callback was not called
even though nineoldandroids has the mechanism to call child animators of AnimatorSet.

  334
             if (.size() > 0) {
335
                 for (Node node : ) {
336
                     node.animation.end();
337
                 }
338
             }


I'm not sure it's not working for both Android Animator and Animation,

Anyway, I used an workaround of setDuration(0).
If I call animator.setDuration(0), it will be finished soon. But, I'm not sure that it will be finished on the same (UI) thread in the same call stack.

You should know the original duration value since you should roll back the duration after the animator ended.

But, getDuration may not be working... ( for the nineoldandroid only?)
Durations should be set on the AnimatorSet (root animator).
Otherwise, animatorSet.getDuration() returns -1.
And, objectAnimator's duration should be set, too, to support this animation on android 2.*.
<set xmlns:android="http://schemas.android.com/apk/res/android"     android:duration="200" >
    <objectAnimator
        android:duration="200"

longgetDuration()
Gets the length of each of the child animations of this AnimatorSet.
abstract AnimatorsetDuration(long duration)
Sets the duration of the animation.


Maybe, you should roll back the duration value of the original animator even though you a cloned animator.
I don't know why.

AnimatorSetclone()
Creates and returns a copy of this Object.






android Volley can't handle redirect responses for twipic images even though we do setFollowRedirect.


I think android volley can't handle redirect responses by default (?)
But, we make URLConnection, which volley uses on android 2.3 (API 9) or higher(?), handles redirects with setFollowRedirects.
You can override HurlStack.createConnection() or simply call HttpURLConnection.setFollowRedirects().

static voidsetFollowRedirects(boolean auto)
Sets the flag of whether this connection will follow redirects returned by the remote server.
voidsetInstanceFollowRedirects(boolean followRedirects)
Sets whether this connection follows redirects.

https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/HurlStack.java
  1.     protected HttpURLConnection createConnection(URL url) throws IOException {
  2.         return (HttpURLConnection) url.openConnection();
  3.     }


But, it still can't handle twipic images.
The reason why was that setFollowRedirects doesn't allow HTTP <--> HTTP redirects.

http://developer.android.com/reference/java/net/HttpURLConnection.html

Response Handling

HttpURLConnection will follow up to five HTTP redirects. It will follow redirects from one origin server to another. This implementation doesn't follow redirects from HTTPS to HTTP or vice versa.


If you still want to fix it, modify the source code of the volley, please.

http://stackoverflow.com/questions/17481964/android-volley-to-handle-redirect
http://stackoverflow.com/questions/19787999/unexpected-response-code-302-for-volley-image-request

Sunday, December 15, 2013

ListView background tuning: Android graphical performance (google io 2013)



Developer options

Show GPU overdraw
Blue 1x
Green 2x
Red 3x
Deep Red 4x

Profile GPU rendering
On screen as bars

If you set own background color on ListView, the android redraw once since android draw windowBackground first.
So, if you move android:background of ListView to style windowBackground, you can reduce one overdraw.

<style name="AppTheme" parent="android:Theme.Light">
<item name="android:windowBackground">@color/dark/background</item>
</style>

https://developers.google.com/events/io/sessions/325418001

http://commondatastorage.googleapis.com/io-2013/presentations/103%20-%20Android%20Graphics%20Performance.pdf




Bonus:



Wednesday, December 11, 2013

It's not simple that debugging android emulator's web page with a chrome beta/canary on PC


I tried doing

Chrome DevTools for Mobile: Emulate and Screencast

https://developers.google.com/chrome-developer-tools/docs/remote-debugging

I recommend you to install
chrome canary
rather than
chrome beta

Chrome canary simply co-exists with the stable chrome on the same machine.
And, it seems to have more developer options.

You should enable some options, first.
about:flags/#enable-devtools-experiments

about:flags/#remote-debugging-raw-usb

Enable Developer Tools experiments. Mac, Windows, Linux, Chrome OS
Enable Developer Tools experiments. Use Settings panel in Developer Tools to toggle individual experiments. 
Enable Remote Debugging over USB. Mac, Windows, Linux, Chrome OS
Enable Remote Debugging of Chrome for Android over raw USB interface (no need to install / run Android Debug Bridge). 

But, there was no google chrome app on my emulator.
I should have put chrome.apk, (or google play apk, ...).
For now, I gave up using an emulator for debugging.

After you connect the usb-debugging device,
enter
about:inspect 
or
chrome://inspect/#devices
on the address of the chrome canary on PC.

You can see your device information,
and go.


To use screencast,
you should install chrome beta on your android device.

Screencasting lets you bring the experience of your device onto your machine. This allows you to keep your attention on one screen instead of switching back and forth between the device and the DevTools. Currently, you need the Chrome for Android Beta (m32) for this feature.

Clicking on the screencast icon Screencast in the toolbar opens up a panel on your computer displaying your device's screen


Chrome for Android Beta on samsung galaxy note 1 was not working well for the screencast.
On nexus 5, it was working well.
Awesome!