2015-04-15

How to parse recoIndex in enex files

According to this Evernote document, recoIndex-es in enex files store OCR scan result. However, they locate deep inside your notes in nested file structures. Actually, I wanted to make a GUI tool to access them easily but I could not spare them to prepare these interface and implement authentication procedures of Evernote. Then, the procedure, shown below, is the temporal answer to me to access recoIndex with ease of read.

  1. Export your target note from any of Evernote client application.
  2. Parse the exported enex file with the following command.
cat /tmp/YOUR_EXPORTED_ENEX_FILE_HERE | xmllint --xpath "//en-export/note/resource/recognition/text()" -|sed -e 's/^$//'|xmllint --pretty 1 -
Results are like this.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE recoIndex PUBLIC "SYSTEM" "http://xml.evernote.com/pub/recoIndex.dtd">
<recoIndex docType="unknown" objType="image" objID="a699335de622d35c5053785f405e639f" engineVersion="6.6.33.2" recoType="service" lang="ja" objWidth="2257" objHeight="2319">
  <item x="34" y="70" w="331" h="101">
    <t w="64">シナプス</t>
    <t w="54">INTス</t>
    <t w="53">ニンナ76ス</t>
    <t w="52">シナ76ス</t>
    <t w="52">シナク6ス</t>
    <t w="50">ニンナク6ス</t>
    <t w="21">16</t>
  </item>
  <item x="500" y="96" w="453" h="97">
    <t w="56">ニュータンの</t>
    <t w="54">ニュートンの</t>
    <t w="53">ニューロンの</t>
    <t w="53">ニューターの</t>
    <t w="52">ニュー畢ヽ一の</t>
    <t w="52">ニュータ一の</t>
    <t w="52">ニュー畢ヽーの</t>
    <t w="52">ニューpI一の</t>
    <t w="52">ニューpIーの</t>
    <t w="52">ニュー専ヽ一の</t>
  </item>

2013-01-28

Brief strategy to mock bfcache on mobile Google Chrome.

(If you liked to apply to your service, further tests will be needed. Please use at your own risk.)
Since Google Chrome for mobile does not store DOM status* of pages they left, you need to write logic to preserve and restore it if you'd like to offer same experience with for existing browsers, like the default browser for Android or PC browsers.

* When you visit Wikipedia from mobile Google Chrome and expand sub categories, then go to another page and return back, you can see that the category you expanded is folded.

Below is an alternate solutions to preserve DOM status with hash fragments.

2012-05-18

A Smater Way to Convert MotionEvent#getRawY() into Relative

I faced a kind of problem. The problem is that MotionEvent#getY() doesn't returns expected values, while MotionEvent#getRawY() keeps returning expected, sequential positions. So I tried to use MotionEvent#getRawY() instead of MotionEvent#getY(). However, values getRawY() sent are based on the absolute position of displays. Some sites show hacks to exclude unnecessary height of, such as the status bar. But the heights of the bars are not same on all platforms and sometimes the bars are even got hidden.

From Android API Level 1(This is not my mistake, indeed from level ONE!), the View class provide getLocationOnScreen(int[]) method. Using this method, you can convert the result of MotionEvent#getRawY() into relative to your views.

class MyView implements OnTouchListener
{
 @Override
 public boolean onTouch(View pmView, MotionEvent pmEvt)
 {
  int[] cViewPosXY = new int[2];
  getLocationOnScreen(cViewPosXY);
  int cTouchX = cEvt.getRawX() - cViewPosXY[0];
  int cTouchY = cEvt.getRawY() - cViewPosXY[1];
 }
}

2012-05-06

BitmapFactory.decodeStream(InputStream)

I desired to generate a new bitmap image with a subclass of java.nio.Buffer for some reason.
I found a simple way to convert Buffer into InputStrem in a post on StackOverFlow titled "java - Wrapping a ByteBuffer with an InputStream"(http://stackoverflow.com/questions/4332264/wrapping-a-bytebuffer-with-an-inputstream). However, I encountered a NPE with the below message on my logcat after integrating my own wrapping ByteBuffer class.
SkImageDecoder::Factory returned null

I investigated this problem and found an essential reason of the message.

2012-04-11

Does The Monkey Tool Launch Not Your Android App But Other Apps?

Someday I faced a problem with my monkey test. The problem was that the monkey command didn't launch my app specified with -p option. At that time, the monkey command launch other apps like alarm which I didn't specified at all.

However, the monkey command launched my app correctly when I specified -p option in the first argument of the monkey command.

$ adb shell
$ monkey -p your.app.package -v 1 ...

I don't know why, but you should specify your package name with -p options in the first argument.

2012-04-06

Get layout values in onCreate method. And Speed up Activity loading times.

Activity#onCreate() is the one of most fundamental methods in Android app creation. However there are some difficulties for this method. For example, you can't obtain layout values of views because layout values are not fixed until the codes in onCreate() methods is done.

But few hacks are left to get layout values in the methods.

The hack is to use IdleHandler (see the IdleHandler description in Android SDK's page). With using IdleHandler, you can run your code after the Android systems finish running current tasks which the UI thread holds.

This hack is also useful to speed up activity loading times, because tasks defined in IdleHandler would be processed after the screen is displayed.

@Override
  public void onCreate(Bundble savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    ...


    Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler()
      {
        @Override
        public boolean queueIdle()
        {
          HEIGHT_OF_MENU_RELATIVE_LAYOUT = findViewById(R.id.main_rlMenu).getHeight();
          return false;
        }
      }
    );
  }
      

2012-03-17

Doesn't your Android app show the default volume control bar?

The above screenshot is taken with a developing version.

Are you troubled with the volume control in your Android app? You're my friends ;-)

I also faced this problem and took a lot of time to fix it. I doubt openal or GLSurfaceView causes this problem. So I try to investigate on the Android source code to know what prevents displaying the default volume control.

But I gave up researching, because the audio management logic of the Android source code is message-based and I found it would take a lot of times to identify the essential factor. In addition to that, I often face this kind of problem even in apps without NDK nor OpenGL.

Then, I found a simple way to display the default volume control. This is just to write explicitly how to handle the volume button events and adjust the volume level manually. It is important to use the flag FLAG_SHOW_UI when adjust the level with AudioManager#setStreamVolume method.

Below is the code, which worked fine for me.