Android app crashes if installed as apk, works if runned trough Android Studio

╄→гoц情女王★ 提交于 2019-12-10 18:34:21

问题


I made an app in Android Studio 2.1.3, that of couse I have tested both in (different) emulators and my own phone (Xiaomi Redmi Note 3, Android 5.0.2 LRX22G). When I gave the apps to a few friends to test they all said the same thing : the app starts normally, they select the activity that they are interested in, they input the data in the textfields and the moment they press the button (that supposes to make some math) to receive the math answers, the app stops and returns to the "main" activity.

compileSdkVersion 24 
buildToolsVersion '23.0.3' 
dexOptions { javaMaxHeapSize "4g" } 
defaultConfig { applicationId "com.example.android.rechner" minSdkVersion 17 
targetSdkVersion 24 
versionCode 4 
versionName 'v.1.6.0 - Entwickler Stufe V.16.9.03' 
multiDexEnabled true

I bought a tablet hoping to get the same crash connected to android studio and get the chance to debug. I sent the apk (debug apk, not release) over BT to the tablet (Teclast Tpad X80 Pro (E3E7), Android 5.1 ), installed the app, and works as it supposed to ! Now I'm getting pissed off ! :) I went to another friend did the same thing as with the tablet, but sent the file to a Samsung Galaxy Grand Prime (didn't look what android version does it have), an crashes when I try to do the math ! He gives me an Samsung Galaxy S3 Mini (GT-I8200N, Android 4.2.2), I send the APK over BT, SAME THING HAPPENS !

Well, I'm starting to be happy because I took the phone with me, I enable developer options, debugging over USB, connect the phone to my computer, load the app with Android Studio, and guess what ?! IT WORKS without any errors, or crases or anything ! I reset the phone to factory settings, hoping to force the error ... I sent the file over BT, and ... IT WORKS ! No errors or crashes whatsoever, though after reset the phone did not connect to my computer (and Android Studio). I fail to see the problem and can't look for answers in a debug log since connected to PC doesn't fail :(

I need to mention that I enabled developer options on the other phones I have tested the app, but the only difference is that none of them were connected to my computer and Android Studio !

Have any of you encountered this problem before ? I have searched for days on our google friend for something similar but didn't found anything.

Thank you for your patience and answers !

Best regards, Robert P.

L.E. I have reflashed the phone, erased cache and data, reinstalled the apk, and finnaly crashes. I succeded to read adb logcat :

W/dalvikvm( 4700): threadid=1: thread exiting with uncaught exception (group=0x40d7d960)
E/AndroidRuntime( 4700): FATAL EXCEPTION: main
E/AndroidRuntime( 4700): java.lang.StringIndexOutOfBoundsException: length=4; regionStart=0; regionLength=-1
E/AndroidRuntime( 4700):        at java.lang.String.startEndAndLength(String.java:583)
E/AndroidRuntime( 4700):        at java.lang.String.substring(String.java:1464)
E/AndroidRuntime( 4700):        at com.example.android.rechner.MainActivityRustZ.displayTimeReal(MainActivityRustZ.java:109)
E/AndroidRuntime( 4700):        at com.example.android.rechner.MainActivityRustZ.access$200(MainActivityRustZ.java:12)
E/AndroidRuntime( 4700):        at com.example.android.rechner.MainActivityRustZ$1.onClick(MainActivityRustZ.java:29)
E/AndroidRuntime( 4700):        at android.view.View.performClick(View.java:4452)
E/AndroidRuntime( 4700):        at android.widget.Button.performClick(Button.java:148)
E/AndroidRuntime( 4700):        at android.view.View$PerformClick.run(View.java:18428)
E/AndroidRuntime( 4700):        at android.os.Handler.handleCallback(Handler.java:725)
E/AndroidRuntime( 4700):        at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 4700):        at android.os.Looper.loop(Looper.java:176)
E/AndroidRuntime( 4700):        at android.app.ActivityThread.main(ActivityThread.java:5365)
E/AndroidRuntime( 4700):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 4700):        at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 4700):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
E/AndroidRuntime( 4700):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
E/AndroidRuntime( 4700):        at dalvik.system.NativeStart.main(Native Method)

now, line 109 : String unitatiTimpReal = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //unit

is part of :

private void displayTimeReal(double timpreal) {
    Double vZeitD = Double.parseDouble(((EditText) findViewById(R.id.vZeit)).getText().toString());
    Double aufStZahl = Double.parseDouble(((EditText) findViewById(R.id.aufGesSt)).getText().toString());
    timpreal = aufStZahl / ((procente / vZeitD) * mitarbeiter);
    DecimalFormat formattr = new DecimalFormat();
    formattr.setMaximumFractionDigits(2);
    formattr.setMinimumFractionDigits(2);
    String formattedTimpR = formattr.format(timpreal);
    String zecimaleTimpReal = formattedTimpR.substring(formattedTimpR.indexOf(".") + 1); //decimals
    String unitatiTimpReal = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //unit
    double minutereal = Double.parseDouble(zecimaleTimpReal);
    minutereal = minutereal * 0.6;
    DecimalFormat format = new DecimalFormat();
    format.setMaximumFractionDigits(2);
    String formattedMinuteReal = format.format(minutereal);
    TextView timeTextView = (TextView) findViewById(R.id.rezultat_ore_real);
    timeTextView.setText(getString(R.string.slaufz) + unitatiTimpReal + getString(R.string.shours) + formattedMinuteReal + getString(R.string.sminutes));
}

Now, the same line is there, the same operation is there, the same apk ... But if I will run the app ONLY once trough Android Studio, until a complete firmware rewrite and cache delete, the app will be running without the crash !

after updating as suggested : this line :

String unitatiTimpReal = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //unit

into :

String unitatiTimpReal;
int index = formattedTimpR.indexOf(".");
if(index != -1) {
unitatiTimpReal = formattedTimpR.substring(0, index);
} else {
// formattedTimpR does not contain ".", handle this somehow
unitatiTimpReal = "";
}

I get this :

W/dalvikvm( 3518): threadid=1: thread exiting with uncaught exception (group=0x40cf4960)
E/AndroidRuntime( 3518): FATAL EXCEPTION: main
E/AndroidRuntime( 3518): java.lang.NumberFormatException: Invalid double: "3,32"
E/AndroidRuntime( 3518):        at java.lang.StringToReal.invalidReal(StringToReal.java:63)
E/AndroidRuntime( 3518):        at java.lang.StringToReal.parseDouble(StringToReal.java:269)
E/AndroidRuntime( 3518):        at java.lang.Double.parseDouble(Double.java:295)
E/AndroidRuntime( 3518):        at com.example.android.rechner.MainActivityRustZ.displayTimeReal(MainActivityRustZ.java:118)
E/AndroidRuntime( 3518):        at com.example.android.rechner.MainActivityRustZ.access$200(MainActivityRustZ.java:12)
E/AndroidRuntime( 3518):        at com.example.android.rechner.MainActivityRustZ$1.onClick(MainActivityRustZ.java:29)
E/AndroidRuntime( 3518):        at android.view.View.performClick(View.java:4452)
E/AndroidRuntime( 3518):        at android.widget.Button.performClick(Button.java:148)
E/AndroidRuntime( 3518):        at android.view.View$PerformClick.run(View.java:18428)
E/AndroidRuntime( 3518):        at android.os.Handler.handleCallback(Handler.java:725)
E/AndroidRuntime( 3518):        at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 3518):        at android.os.Looper.loop(Looper.java:176)
E/AndroidRuntime( 3518):        at android.app.ActivityThread.main(ActivityThread.java:5365)
E/AndroidRuntime( 3518):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 3518):        at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 3518):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
E/AndroidRuntime( 3518):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
E/AndroidRuntime( 3518):        at dalvik.system.NativeStart.main(Native Method)

line 118 is :

        double minutereal = Double.parseDouble(zecimaleTimpReal);

@user13 What I want to achieve : Among a few other calculations that I do for the user, based on the data it inputs, I transform industrial time in real time (procentual time in minutes, hours (more exactly 100 minutes industrial time in 60 minutes normal time)

private void displayTimeReal(double timpreal) {

initialising var vZeitD as double, that user is required to input for the math operation

Double vZeitD = Double.parseDouble(((EditText) findViewById(R.id.vZeit)).getText().toString());

initialising var aufStZahl as double, that user is required to input for the math operation - here I can modify in integer because only integers are allowed to be input

Double aufStZahl = Double.parseDouble(((EditText) findViewById(R.id.aufGesSt)).getText().toString());

The math done to show the time required (but is in industrial time, that is 100 minutes)

timpreal = aufStZahl / ((procente / vZeitD) * mitarbeiter);

I split up the answer (as example 12.75, where 12 is hours and 75 are the minutes) and I set the maximum an minimum displayed decimals (2) :

DecimalFormat formattr = new DecimalFormat();
formattr.setMaximumFractionDigits(2);
formattr.setMinimumFractionDigits(2);
String formattedTimpR = formattr.format(timpreal);

taking the decimals to be converted from industrial

    String zecimaleTimpReal = formattedTimpR.substring(formattedTimpR.indexOf(".") + 1); //decimals

taking the units from the resulted number after the math done (units remain to be displayes as they are

String unitatiTimpReal = formattedTimpR.substring(0, formattedTimpR.indexOf(".")); //unit

since I have to do math again, I can't use strings and I convert the decimals in double and I do the conversion to real time (60 minutes)

double minutereal = Double.parseDouble(zecimaleTimpReal);
minutereal = minutereal * 0.6;

I set again the maximum number of decimals (so that I don't show a response like 39.326562365) for the minutes (ex : 39.33 minutes instead of 39.326562365)

DecimalFormat format = new DecimalFormat();
format.setMaximumFractionDigits(2);
String formattedMinuteReal = format.format(minutereal);

displaying the result to the user :

TextView timeTextView = (TextView) findViewById(R.id.rezultat_ore_real);
timeTextView.setText(getString(R.string.slaufz) + unitatiTimpReal + getString(R.string.shours) + formattedMinuteReal + getString(R.string.sminutes));
}

回答1:


The problem seems to be caused by the numbers being formatted differently based on the devices's Locale.

When you use a DecimalFormat object, the decimal separator is different depending on the device's language settings. For example in English it's a dot e.g. 3.14159 but in German it's a comma e.g. 3,14159.

This causes a problem because your code is always looking for a dot when you call indexOf().

You can fix this several ways. One way is to specify a locale when creating the DecimalFormat object, e.g:

NumberFormat nf = NumberFormat.getNumberInstance(Locale.ENGLISH);
DecimalFormat formattr = (DecimalFormat)nf;

Or else you can just set the decimal separator:

DecimalFormat formattr = new DecimalFormat();
formattr.setDecimalSeparator('.');

However perhaps you want it to display differently for German users. In that case you can change your code that checks for the dot to check for whatever the correct character is:

String zecimaleTimpReal = formattedTimpR.substring(formattedTimpR.indexOf("" + formattr.getDecimalFormatSymbols().getDecimalSeparator()) + 1);

Adding to the empty string is just a trick to convert from a char to a String.

Be aware that there is also a "grouping symbol" which can be a comma or dot as well e.g. 123,456.78. You might want to disable grouping, like this:

formattr.setGroupingUsed(false);



回答2:


The problem is in line 109 formattedTimpR does not contain the String ".".

Because of this, the indexOf() methods returns -1, so basically you're calling substring(0, -1), hence the error.

I do not really see what you would like to achive, but you could at least do a check before calling substring(), something like this:

String unitatiTimpReal;
int index = formattedTimpR.indexOf(".");
if(index != -1) {
    unitatiTimpReal = formattedTimpR.substring(0, index);
} else {
    // formattedTimpR does not contain ".", handle this somehow
    unitatiTimpReal = "";
}


来源:https://stackoverflow.com/questions/39316379/android-app-crashes-if-installed-as-apk-works-if-runned-trough-android-studio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!