Using java.util.regex in Android apps - are there issues with this? - android

In an Android app I have a utility class that I use to parse strings for 2 regEx's. I compile the 2 patterns in a static initializer so they only get compiled once, then activities can use the parsing methods statically.
This works fine except that the first time the class is accessed and loaded, and the static initializer compiles the pattern, the UI hangs for close to a MINUTE while it compiles the pattern! After the first time, it flies on all subsequent calls to parseString().
My regEx that I am using is rather large - 847 characters, but in a normal java webapp this is lightning fast. I am testing this so far only in the emulator with a 1.5 AVD.
Could this just be an emulator issue or is there some other reason that this pattern is taking so long to compile?
private static final String exp1 = "(insertratherlong---847character--regexhere)";
private static Pattern regex1 = null;
private static final String newLineAndTagsExp = "[<>\\s]";
private static Pattern regexNewLineAndTags = null;
static {
regex1 = Pattern.compile(exp1, Pattern.CASE_INSENSITIVE);
regexNewLineAndTags = Pattern.compile(newLineAndTagsExp);
}
public static String parseString(CharSequence inputStr) {
String replacementStr = "replaceMentText";
String resultString = "none";
try {
Matcher regexMatcher = regex1.matcher(inputStr);
try {
resultString = regexMatcher.replaceAll(replacementStr);
} catch (IllegalArgumentException ex) {
} catch (IndexOutOfBoundsException ex) {
}
} catch (PatternSyntaxException ex) {
}
return resultString;
}

please file a reproduceable test case at http://code.google.com/p/android/issues/entry and i'll have a look. note that i will need a regular expression that reproduces the problem. (our regular expressions are implemented by ICU4C, so the compilation actually happens in native code and this may end up being an ICU bug, but if you file an Android bug i'll worry about upstream.)

If you launched with debugging you can expect it to be about twice as slow as a regular launch. However a minute does seem extraordinary. Some things to suggest, i. look at the console output to see if warnings are being spat out, ii. when it is doing the compile, in the debugger press 'pause' and just see what it is doing. There are ways to get the source, but even so just looking at the call stack may reveal something.

Related

Low Rhino performance on android real device

I'm having low Rhino performance issues while executing Rhino code on Android real device.
The Rhino context is initiated with a string which represents big JSON object, the total string size is around 120K, to test code performance we wrote a few instrumental tests to check the code performance, however, we are getting not clear result the same code, with the same parameters shows absolutely different results between tests and sample app.
The test performance 10 times faster than the same code is executed as an instrumental test then on it's running as part of the sample app on the same device (G5). BTW the android emulator also shows good performance result.
the code is pretty simple
private void init(String jFfunctionsDeclaration) throws ScriptInitException {
StringBuilder ruleEngineContextBuffer = new StringBuilder();
//create a JSON object in the string representation, later Rhino context will be initialized with this string
for (Map.Entry<String, String> e : scriptObjects.entrySet()) {
String key = e.getKey();
String value = e.getValue();
ruleEngineContextBuffer.append("\nvar ");
ruleEngineContextBuffer.append(key);
ruleEngineContextBuffer.append(" = "); // append(" = JSON.parse(");
ruleEngineContextBuffer.append(value);
}
// create and enter safe execution context to prevent endless loop or deadlock in JS
// because Rhino input it provided from outside
SafeContextFactory safeContextFactory = new SafeContextFactory();
rhino = safeContextFactory.makeContext().enter();
try {
// the fisrt init step, init Rhino cotext with JS utils methods
// functions input is the list of JS functions
sharedScope = rhino.initStandardObjects();
rhino.evaluateString(sharedScope, functions, "<init1>", 1, null);
String str = ruleEngineContextBuffer.toString();
long startContextInit = System.currentTimeMillis();
rhino.evaluateString(sharedScope, str, "<init2>", 1, null);
long totalContextInit = System.currentTimeMillis() - startContextInit;
Log.d(TAG, "Rhino context init duration = " + totalContextInit);
} catch (Throwable e) {
throw new ScriptInitException("Javascript shared scope initialization error: " + e.getMessage());
}
}
could someone explain me this mystery, thanks.

How can I pass data to libcore on Android?

I was modifying the libcore on Andorid for debugging purpose.
It took a lot of time to build even for a variable change.
Is it possible to pass the data to libcore of android?
(so I can change the data in the running time).
I tried System.getProperty() but the data could not cross process.
I also tried SystemProperties.get() but it seems it can not be used in libcore (it could not find the package and symbol).
Does anyone know how to pass data to the libcore on Android?
Thanks Nativ.
JNI is doable but a little complicated for me.
Finally, I used a simple, easy but stupid way to do that.
I created a file and saved my parameter in this file, and get the data from libcore.
It is a stupid way but worked for me for debugging.
Now I don't need to rebuild libcore and It saved much for me.
You can use reflection on class android.os.SystemProperties to get System Properties at runtime.
Code example:
public static String getSystemProperty(String key) {
String value = "";
try {
Class clazz = Class.forName("android.os.SystemProperties");
if (clazz != null) {
Object object = clazz.newInstance();
value = (String) (clazz.getMethod("get", String.class).invoke(object, key));
} else {
System.err.println(TAG + ", getSystemProperty: Class is null.");
}
} catch (Exception e) {
e.printStackTrace();
}
return value;
}

Getting ProtoBuf.ProtoException using OsmSharp in Xamarin Android

I am trying to test a sample project called Android.Routing.Offline from OsmSharp.Samples in Github.
After two taps on the screen (the first one gets just the GeoCoordinate) I get a ProtoBuf.ProtoException in the Router.cs
private static IBasicRouterDataSource<CHEdgeData> _graph;
public static void Initialize()
{
var routingSerializer = new CHEdgeDataDataSourceSerializer();
_graph = routingSerializer.Deserialize(
Assembly.GetExecutingAssembly().GetManifestResourceStream(#"Android.Routing.Offline.kempen-big.contracted.mobile.routing"));
}
public static Route Calculate(GeoCoordinate from, GeoCoordinate to)
{
try
{
lock(_graph)
{
var router = Router.CreateCHFrom(_graph, new CHRouter(), new OsmRoutingInterpreter());
// The exception happens here below
var fromResolved = router.Resolve(Vehicle.Car, from);
var toResolved = router.Resolve(Vehicle.Car, to);
if(fromResolved != null && toResolved !=null)
{
return router.Calculate(Vehicle.Car, fromResolved, toResolved);
}
}
}
catch(Exception ex)
{
OsmSharp.Logging.Log.TraceEvent("Router", OsmSharp.Logging.TraceEventType.Critical, "Unhandled exception occured: {0}", ex.ToString());
}
return null;
}
And the exception:
> {ProtoBuf.ProtoException: Invalid wire-type; this usually means you
> have over-written a file without truncating or setting the length; see
> http://stackoverflow.com/q/2152978/23354 at
> ProtoBuf.ProtoReader.ReadSingle () ...
I didnt overwrite the file (kempen-big.contracted.mobile.routing) just added it as a linked file in the project. Any ideas how I can solve this issue?
Well, the first thing to try is to check that the contents of the Stream you are reading (via GetManifestResourceStream) contains exactly the contents you are expecting, and not some wrapper or otherwise-corrupt mess. If you have some checksum algorithm you can run: great! Checking just the .Length would be a great start. Otherwise, you could cheat (just for the purposes of validating the contents) by getting the hex:
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
string hex = BitConverter.ToString(
ms.GetBuffer(), 0, (int)ms.Length);
// dump this string, and compare it to the same output run on the
// oringal file; they should be identical
}
Note that this duplicates the contents in-memory, purely so we can get a byte[] (oversized) to get the hex from - it isn't intended for "real" code, but until you are sure that the contents are correct, all other bets are off. I strongly suspect that you'll find that the contents are not identical to the contents in the original file. Note that I'm also implicitly assuming that the original file works fine in terms of deserialization. If the original file doesn't work: again, all bets are off.

Android parseDouble returns Infinity when it should throw NumberFormatException

I'm trying to determine if a String represents a Double. I expect the following code to throw a NumberFormatException:
String s = "type1234";
try {
Double val = Double.parseDouble(s);
} catch (NumberFormatException e) {
// Handle exception
e.printStackTrace();
}
Instead, val ends up with Infinity. I ran the code in a standard JVM and it does, indeed, throw NumberFormatException
It looks like Android is ignoring the leading characters 'typ' and then parsing it as e^1234, which is out of Double's range.
Is this the expected behavior? If so, what is a more reliable way to determine if a String can be parsed as a Double?
Use a regular expression to validate yourself if you don't trust the framework. Here's an example of one way to do this.
// You can get much fancier than this to handle all cases, but this should handle most
String regexDouble = "^-?\\d*(\\.\\d+)?$";
boolean isDouble = val.matches(regexDouble);
Fastest way to check if a String can be parsed to Double in Java
The answer on this post works on android. I have tested it on ICS.

android is it possible for an app to detect when it is running on emulator vs device

I develop a game that is heavily dependent upon timing, when I run it in the emulator it executes understandably slower than when I run it on my phone. This forces me to up all the "stats" in my game, so that I can actually "beat it" when I am developing - when Debugging, the game is unwinnable.
Is there a call, or variable, or something that I can use to determine whether I am currently running on the Emulator and not a device.
I've considered trying to detect if Framerate is low.
I've considered trying to read the "device name" from some sort of build in system field.
But neither seems like a very good method to pursue.
Any help would be great.
Use the Build.DEVICE value and compare to "sdk".
First idea:check the network operator, on the emulator, it's always equal to "Android". Not documented and just a guess that it will work everytime!
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tm.getNetworkOperatorName();
if("Android".equals(networkOperator)) {
// Emulator
}
else {
// Device
}
Second idea: the manufacturer:
public boolean isEmulator() {
return Build.MANUFACTURER.equals("unknown");
}
Third idea: seem th best one, check the debug key:
static final String DEBUGKEY =
"get the debug key from logcat after calling the function below once from the emulator";
public static boolean signedWithDebugKey(Context context, Class<?> cls)
{
boolean result = false;
try {
ComponentName comp = new ComponentName(context, cls);
PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES);
Signature sigs[] = pinfo.signatures;
for ( int i = 0; i < sigs.length;i++)
Log.d(TAG,sigs[i].toCharsString());
if (DEBUGKEY.equals(sigs[0].toCharsString())) {
result = true;
Log.d(TAG,"package has been signed with the debug key");
} else {
Log.d(TAG,"package signed with a key other than the debug key");
}
} catch (android.content.pm.PackageManager.NameNotFoundException e) {
return false;
}
return result;
}
from here: How can I detect when an Android application is running in the emulator?
If you're using Google APIs, you want:
"google_sdk".equals( Build.PRODUCT );
If not, you'll want to use:
"sdk".equals( Build.PRODUCT );
The older (since deprecated) way to do this was to check ANDROID_ID, which is null on the AVD, but this doesn't work on API 7 and above:
// ONLY WORKS ON 2.1 AND BELOW
String android_id = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
if (android_id == null) {
// Emulator!
} else {
// Device
}
Dan S gave a good answer about how to detect when running on the emulator. However, a few tips:
Instead of relying on something in the SDK, why not just set up your own flag? Just keep a public final static boolean isEmulator that you change from true to false depending on the environment, and build your code with ifs and elses around it. The Build.DEVICE method is not 100% safe, since some rooted devices might have that borked.
Low framerate detection could be a good thing to implement. Given the wide range of Android devices, it might prove helpful on lower-end ones.

Categories

Resources