Jump To Topic
The following recipes include tips on making your Codename One apps more secure.
Detecting Jailbroken/Rooted Device
Problem
You want to detect whether the device your app is running on is Jailbroken or Rooted.
Solution
While there is no way to know whether the device is rooted with 100% certainty, you can use the CN1JailbreakDetect cn1lib to to make a good guess.
This cn1lib acts as a thin wrapper around the RootBeer Android library, and DTTJailbreakDetection iOS library, which employ heuristics to determine whether the device has likely been jailbroken.
Example
package com.codename1.samples;
import com.codename1.ext.jailbreak.JailbreakDetect;
import static com.codename1.ui.CN.*;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Dialog;
import com.codename1.ui.Label;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.ui.Toolbar;
import java.io.IOException;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.io.NetworkEvent;
import com.codename1.ui.Button;
import com.codename1.ui.Command;
public class JailbreakDetectionSample {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Jailbreak Detection", BoxLayout.y());
Button detect = new Button("Detect Jailbreak");
detect.addActionListener(evt->{
if (JailbreakDetect.isJailbreakDetectionSupported()) {
if (JailbreakDetect.isJailbroken()) {
Dialog.show("Jailbroken","This device is jailbroken", new Command("OK") );
} else {
Dialog.show("Not Jailbroken", "Probably not jailbroken. But can't be 100% sure.", new Command("OK"));
}
} else {
Dialog.show("No Idea", "No support for jailbreak detection on this device.", new Command("OK"));
}
});
hi.add(detect);
hi.show();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
Tip:
This sample is part of the Codename One samples project, and can be run directly from the Codename One SampleRunner.
Discussion
The CN1JailbreakDetect provides two useful static methods for jailbreak detection:
2. isJailBroken() – This checks if the device is jailbroken. If detection is not supported, then this will always return false.
Currently jailbreak detection is only supported on Android and iOS.
Important:
There is NO way to know with 100% certainty whether or not a device has been jailbroken.
Further Reading
RootBeer project (Used on Android)
DTTJailbreakDetection project (Used on iOS)
Hiding Sensitive Data When Entering Background
Problem
iOS will take a screenshot of your app when it enters the background that it uses for various previews of the app state. You want to hide sensitive data in your app’s UI to prevent this information from leaking out via these screenshots.
Solution
Warning:
This will cause your app to appear as a blank white rectangle when the user is browsing through opened apps.
Figure 1. Notice the app in the middle is blank white because it has been set to block iOS screenshots.
Discussion
This strategy will work in some platforms, but not on iOS because the screenshot call is made immediately upon the didEnterBackground method returning – and the stop() method runs on the EDT (a different thread), so this is not possible.
4 Comments
Very useful. There are lots of rooted users that hack in-app purchases and get things for free. I wonder how effective RootBeer is, I know there are tools available to hide the root at the moment
Just looked at the RootBeer code and it looks great. It even checks natively in cpp, which I read was the safest way to bypass root masks
Is there any reason RootBeer version 0.0.8 is used and not 0.0.9?
Nevermind, I just added the native bits myself. Wish I could delete/edit my posts on here, maybe that could be enabled at some point