Build Your Personal English Learning Assistant with Android

2 minute read

I want to improve my English, one way to do this is watching documentaries on TV, but subtitles distract me from the video themselves, I get this around by masking them with a always on top window placing at the bottom area.

I named this project as Pela, the Personal English Learning Assistant.

Always on Top Window

Speaking of the top window, there are plenty of options out there, like facebook like Chathead, or libraries like StandOut.

For simplicity I prefer the former one, the final work looks like this: English Learning Assistant

First create a project with Android Studio, then add permission and our service to AndroidManifest.xml

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <service android:name=".ELAssistantService" />

Create a service named ELAssistantService, overrides method onCreate() to add view to the WindowManager:

public void onCreate() {
    super.onCreate();
    mView = new LinearLayout(this);
    mView.setBackgroundColor(Color.GRAY);
    LayoutParams params = new LayoutParams(
            width, height,
            LayoutParams.TYPE_SYSTEM_OVERLAY,
            0,
            PixelFormat.TRANSLUCENT);
    params.gravity = Gravity.CENTER | Gravity.BOTTOM;
    params.y = 20;

    WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
    wm.addView(mView, params);
}

The last step is to start service in MainActivity.java:

startService(new Intent(getApplication(), ELAssistantService.class));

Launching this app will lead to a AndroidRuntime exception:

10-19 11:21:03.829  8203  8203 E AndroidRuntime: java.lang.RuntimeException: Unable to create service com.bay.elassistant.ELAssistantService: android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@d344ffc -- permission denied for this window type

To get this working, SYSTEM_ALERT_WINDOW permission needs to be granted, best way to do this is to prompt user to accept it, but for some android systems that lacks of SystemUI.apk, this is not happening, the following command do the trick:

adb shell appops set applicationId SYSTEM_ALERT_WINDOW allow

And the applicationId can be found in app/build.gradle:

ELAssistant rg applicationId
app/build.gradle
7:        applicationId "com.bay.elassistant"

Issue this command: adb shell appops set com.bay.elassistant SYSTEM_ALERT_WINDOW allow and launch the app to start watching now.

Start Service on Boot Completed

This is optional, for convenience I want it show up automatically, so I don’t need to launch this app when I want to watch TV, add these to AndroidManifest.xml:

<receiver android:name=".ELAssistantBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

And create a service(ELAssistantBroadcastReceiver.java) to handle boot completed intent:

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.Context;

public class ELAssistantBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        context.startService(new Intent(context, ELAssistantService.class));
    }
}

Future work

The next step I want to do is to make the floating window self-adaptive according the position of the subtitles detected, for doing this the first thing to do is contour detection. Lars Nieradzik has already did this in his project chinese subtitle ocr using SSD(Single Shot MultiBox Detector), what I need to do is make this works on Android, this tutorial for opencv could be a good starting point.

References

Updated: