好吧,我有一个问题。刚刚结束编写应用程序并在我的 Android 模拟器上启动它,一切正常,没有任何错误或类似的东西。但是当我在我的真实设备(Android 2.3.5 GingerBread)上尝试这个应用程序时,我的应用程序甚至没有启动,并且我的 Logcat 中出现了一堆错误而被强制关闭。在这里,我将提供我的代码。
活动主.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".CrazyTipCalc" >
<TextView
android:id="@+id/billTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:layout_marginTop="14dp"
android:text="@string/bill_text_view" />
<!-- android:ems defines the width of the EditText box -->
<EditText
android:id="@+id/billEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_toRightOf="@+id/billTextView"
android:ems="5"
android:inputType="numberDecimal"
android:text="@string/bill_edit_text" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/tipTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/billTextView"
android:layout_marginLeft="15dp"
android:layout_toRightOf="@+id/billEditText"
android:text="@string/tip_text_view" />
<EditText
android:id="@+id/tipEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/finalBillTextView"
android:layout_marginLeft="18dp"
android:layout_toRightOf="@+id/tipTextView"
android:ems="4"
android:inputType="numberDecimal"
android:text="@string/tip_edit_text" />
<TextView
android:id="@+id/finalBillTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/finalBillEditText"
android:layout_below="@+id/billEditText"
android:layout_marginTop="14dp"
android:text="@string/final_bill_text_view" />
<EditText
android:id="@+id/finalBillEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/tipEditText"
android:layout_below="@+id/finalBillTextView"
android:ems="5"
android:inputType="numberDecimal"
android:text="@string/final_bill_edit_text" />
<TextView
android:id="@+id/changeTipTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="@+id/finalBillTextView"
android:layout_alignLeft="@+id/billTextView"
android:text="@string/change_tip_text_view" />
<!-- android:progress="15" defines the default for the SeekBar -->
<SeekBar
android:id="@+id/changeTipSeekBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/changeTipTextView"
android:layout_alignTop="@+id/finalBillEditText"
android:layout_marginTop="14dp"
android:layout_toLeftOf="@+id/tipTextView"
android:progress="15" />
<TextView
android:id="@+id/introTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/changeTipSeekBar"
android:layout_below="@+id/changeTipSeekBar"
android:layout_marginTop="14dp"
android:text="@string/intro_text_view" />
<CheckBox
android:id="@+id/friendlyCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/introTextView"
android:layout_below="@+id/introTextView"
android:layout_marginTop="14dp"
android:text="@string/intro_friendly_text_view" />
<CheckBox
android:id="@+id/specCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/friendlyCheckBox"
android:layout_alignBottom="@+id/friendlyCheckBox"
android:layout_toRightOf="@+id/friendlyCheckBox"
android:text="@string/intro_spec_text_view" />
<CheckBox
android:id="@+id/opinionCheckBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/specCheckBox"
android:layout_alignBottom="@+id/specCheckBox"
android:layout_alignParentRight="true"
android:text="@string/intro_opinion_text_view" />
<TextView
android:id="@+id/availableTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/friendlyCheckBox"
android:layout_centerVertical="true"
android:text="@string/available_text_view" />
<RadioGroup
android:id="@+id/availableRadioGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/friendlyCheckBox"
android:layout_below="@+id/availableTextView"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/availableBadRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/available_bad_radio_button" />
<RadioButton
android:id="@+id/availableOkRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/available_ok_radio_button" />
<RadioButton
android:id="@+id/availableGoodRadio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/available_good_radio_button" />
</RadioGroup>
<TextView
android:id="@+id/timeWaitingTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/problemSpinner"
android:layout_below="@+id/problemSpinner"
android:layout_marginTop="17dp"
android:text="@string/time_waiting_text_view" />
<Chronometer
android:id="@+id/timeWaitingChronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/availableRadioGroup"
android:layout_alignTop="@+id/timeWaitingTextView"
android:text="Chronometer" />
<Spinner
android:id="@+id/problemSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/availableRadioGroup"
android:layout_below="@+id/availableRadioGroup"
android:layout_marginTop="14dp"
android:entries="@array/problem_solving" />
<Button
android:id="@+id/startChronometerButton"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/timeWaitingTextView"
android:layout_alignParentBottom="true"
android:text="@string/start_chronometer_button" />
<Button
android:id="@+id/pauseChronometerButton"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/startChronometerButton"
android:layout_alignBottom="@+id/startChronometerButton"
android:layout_toRightOf="@+id/changeTipTextView"
android:text="@string/pause_chronometer_button" />
<Button
android:id="@+id/resetChronometerButton"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/pauseChronometerButton"
android:layout_alignBottom="@+id/pauseChronometerButton"
android:layout_toRightOf="@+id/timeWaitingTextView"
android:text="@string/reset_chronometer_button" />
</RelativeLayout>
MainActivity.java :
package com.example.crazytipcalc;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.CompoundButton;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;
public class MainActivity extends Activity {
// Constants used when saving and restoring
private static final String TOTAL_BILL = "TOTAL_BILL";
private static final String CURRENT_TIP = "CURRENT_TIP";
private static final String BILL_WITHOUT_TIP = "BILL_WITHOUT_TIP";
// Set default values for EditText's
private double billBeforeTip;
private double tipAmount;
private double finalBill;
// Declare EditTexts
EditText billBeforeTipET;
EditText tipAmountET;
EditText finalBillET;
// Sum of all radio buttons and check boxes
private int[] checkListValues = new int[12];
// Declare CheckBoxes
CheckBox friendlyCheckBox;
CheckBox specCheckBox;
CheckBox opinionCheckBox;
// Declare RadioButtons
RadioGroup availableRadioGroup;
RadioButton availableBadRadio;
RadioButton availableOkRadio;
RadioButton availableGoodRadio;
// Declare Spinner
Spinner problemSpinner;
// Declare Buttons
Button startChronometerButton;
Button pauseChronometerButton;
Button resetChronometerButton;
// Declare chronometer
Chronometer timeWaitingChronometer;
// The number of seconds you spent
// wating for the waitress
long secondsYouWaited = 0;
// TextView for the chronometer
TextView timeWaitingTextView;
// Declare Seekbar
SeekBar tipSeekBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check if app just started, or if it is being restored
if (savedInstanceState == null) {
// Just started
billBeforeTip = 0.0;
tipAmount = .15;
finalBill = 0.0;
} else {
// App is being restored
billBeforeTip = savedInstanceState.getDouble(BILL_WITHOUT_TIP);
tipAmount = savedInstanceState.getDouble(CURRENT_TIP);
finalBill = savedInstanceState.getDouble(TOTAL_BILL);
}
/* INITIALIZING ALL THE VARIABLES AND ID'S */
// Initialize EditTexts
billBeforeTipET = (EditText) findViewById(R.id.billEditText);
tipAmountET = (EditText) findViewById(R.id.tipEditText);
finalBillET = (EditText) findViewById(R.id.finalBillEditText);
// Initialize Seekbar and add ChangeListener
tipSeekBar = (SeekBar) findViewById(R.id.changeTipSeekBar);
tipSeekBar.setOnSeekBarChangeListener(tipSeekBarListener);
// Add change listener for when the bill before tip is changed
billBeforeTipET.addTextChangedListener(billBeforeTipListener);
// Initialize CheckBoxes
friendlyCheckBox = (CheckBox) findViewById(R.id.friendlyCheckBox);
specCheckBox = (CheckBox) findViewById(R.id.specCheckBox);
opinionCheckBox = (CheckBox) findViewById(R.id.opinionCheckBox);
setUpIntroCheckBoxes();
// Initialize RadioButtons
availableRadioGroup = (RadioGroup) findViewById(R.id.availableRadioGroup);
availableBadRadio = (RadioButton) findViewById(R.id.availableBadRadio);
availableOkRadio = (RadioButton) findViewById(R.id.availableOkRadio);
availableGoodRadio = (RadioButton) findViewById(R.id.availableGoodRadio);
addChangeListenerToRadios();
// Initialize Spinner
problemSpinner = (Spinner) findViewById(R.id.problemSpinner);
addItemSelectedListenerToSpinner();
// Initialize buttons
startChronometerButton = (Button) findViewById(R.id.startChronometerButton);
pauseChronometerButton = (Button) findViewById(R.id.pauseChronometerButton);
resetChronometerButton = (Button) findViewById(R.id.resetChronometerButton);
setButtonsOnClickListener();
// Initialize chronometer
timeWaitingChronometer = (Chronometer) findViewById(R.id.timeWaitingChronometer);
// Initialize TextView
timeWaitingTextView = (TextView) findViewById(R.id.timeWaitingTextView);
}
// Called when the bill before tip amount is changed
private TextWatcher billBeforeTipListener = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
try {
// Change the billBeforeTip to the new input
billBeforeTip = Double.parseDouble(s.toString());
} catch (NumberFormatException e) {
// Else make it default
billBeforeTip = 0.0;
}
updateTipAndFinalBill();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
};
// Update the tip amount and add tip to bill to
// find the final bill amount
private void updateTipAndFinalBill() {
// Get tip amount
double tipAmount = Double.parseDouble(tipAmountET.getText().toString());
// The bill before tip amount was set in billBeforeTipListener
// Get the bill plus the tip
double finalBill = billBeforeTip + (billBeforeTip * tipAmount);
// Set the total bill amount including the tip
finalBillET.setText(String.format("%.02f", finalBill));
}
// Called when a device changes in some way. For example,
// when a keyboard is popped out, or when the device is
// rotated. Used to save state information that you'd like
// to be made available.
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putDouble(TOTAL_BILL, finalBill);
outState.putDouble(CURRENT_TIP, tipAmount);
outState.putDouble(BILL_WITHOUT_TIP, billBeforeTip);
}
private OnSeekBarChangeListener tipSeekBarListener = new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// Get the value set on the SeekBar
tipAmount = (tipSeekBar.getProgress()) * .01;
// Set tipAmountET with the value from the SeekBar
tipAmountET.setText(String.format("%.02f", tipAmount));
// Update all the other EditTexts
updateTipAndFinalBill();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
};
private void setUpIntroCheckBoxes() {
// Add ChangeListener to the friendlyCheckBox
friendlyCheckBox
.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0,
boolean arg1) {
// Use java ternary operator to set the right values for
// each item on the waitress check box checklist
checkListValues[0] = (friendlyCheckBox.isChecked()) ? 4
: 0;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
});
// Add ChangeListener to the specialsCheckBox
specCheckBox
.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0,
boolean arg1) {
// Use java ternary operator to set the right values for
// each item on the waitress check box checklist
checkListValues[1] = (specCheckBox.isChecked()) ? 1 : 0;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
});
// Add ChangeListener to the opinionCheckBox
opinionCheckBox
.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton arg0,
boolean arg1) {
// Use java ternary operator to set the right values for
// each item on the waitress check box checklist
checkListValues[2] = (opinionCheckBox.isChecked()) ? 2
: 0;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
});
}
// Calculate tip using the waitress checklist options
private void setTipFromWaitressChecklist() {
int checkListTotal = 0;
// Circle through all the checklist values to calculate
// a total amount based on waitress performance
for (int item : checkListValues) {
checkListTotal += item;
}
// Set tipAmountET
tipAmountET.setText(String.format("%.02f", checkListTotal * .01));
}
private void addChangeListenerToRadios() {
availableRadioGroup
.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
checkListValues[3] = (availableBadRadio.isChecked()) ? -1
: 0;
checkListValues[4] = (availableOkRadio.isChecked()) ? 2
: 0;
checkListValues[5] = (availableGoodRadio.isChecked()) ? 4
: 0;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
});
}
private void addItemSelectedListenerToSpinner() {
problemSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
checkListValues[6] = (problemSpinner.getSelectedItem())
.equals("Bad") ? -1 : 0;
checkListValues[7] = (problemSpinner.getSelectedItem())
.equals("OK") ? 3 : 0;
checkListValues[8] = (problemSpinner.getSelectedItem())
.equals("Good") ? 6 : 0;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
}
// Adds ClickListeners for buttons so they can control the chronometer
private void setButtonsOnClickListener() {
startChronometerButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Holds the number of milliseconds paused
int stoppedMiliseconds = 0;
// Get time from the chronometer
String chronoText = timeWaitingChronometer.getText().toString();
String array[] = chronoText.split(":");
if (array.length == 2) {
// Find the seconds
stoppedMiliseconds = Integer.parseInt(array[0]) * 60 * 1000
+ Integer.parseInt(array[1]) * 1000;
} else if (array.length == 3) {
// Find the minutes
stoppedMiliseconds = Integer.parseInt(array[0]) * 60 * 60
* 1000 + Integer.parseInt(array[1]) * 60 * 1000
+ Integer.parseInt(array[2]) * 1000;
}
// Amount of time elapsed since the start button was
// pressed, minus the time paused
timeWaitingChronometer.setBase(SystemClock.elapsedRealtime()
- stoppedMiliseconds);
// Set the number of seconds you have waited
// This would be set for minutes in the real world
// obviously. That can be found in array[2]
secondsYouWaited = Long.parseLong(array[1]);
updateTipBasedOnTimeWaited(secondsYouWaited);
// Start the chronometer
timeWaitingChronometer.start();
}
});
pauseChronometerButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
timeWaitingChronometer.stop();
}
});
resetChronometerButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
timeWaitingChronometer.setBase(SystemClock.elapsedRealtime());
secondsYouWaited = 0;
}
});
}
private void updateTipBasedOnTimeWaited(long secondsYouWaited) {
checkListValues[9] = (secondsYouWaited > 10) ? -2 : 2;
// Calculate tip using the waitress checklist options
setTipFromWaitressChecklist();
// Update all the other EditTexts
updateTipAndFinalBill();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.crazytipcalc"
android:versionCode="1"
android:versionName="1.0"
android:installLocation="preferExternal" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.crazytipcalc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
日志猫:
07-14 21:50:27.710: I/ApplicationPackageManager(3211): cscCountry is not German : SEB
07-14 21:50:27.921: D/AndroidRuntime(3211): Shutting down VM
07-14 21:50:27.921: W/dalvikvm(3211): threadid=1: thread exiting with uncaught exception (group=0x40018578)
07-14 21:50:27.929: E/AndroidRuntime(3211): FATAL EXCEPTION: main
07-14 21:50:27.929: E/AndroidRuntime(3211): java.lang.NumberFormatException
07-14 21:50:27.929: E/AndroidRuntime(3211): at org.apache.harmony.luni.util.FloatingPointParser.parseDblImpl(Native Method)
07-14 21:50:27.929: E/AndroidRuntime(3211): at org.apache.harmony.luni.util.FloatingPointParser.parseDouble(FloatingPointParser.java:283)
07-14 21:50:27.929: E/AndroidRuntime(3211): at java.lang.Double.parseDouble(Double.java:318)
07-14 21:50:27.929: E/AndroidRuntime(3211): at com.example.crazytipcalc.MainActivity.updateTipAndFinalBill(MainActivity.java:217)
07-14 21:50:27.929: E/AndroidRuntime(3211): at com.example.crazytipcalc.MainActivity.access$1(MainActivity.java:213)
07-14 21:50:27.929: E/AndroidRuntime(3211): at com.example.crazytipcalc.MainActivity$7.onItemSelected(MainActivity.java:429)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.widget.AdapterView.fireOnSelected(AdapterView.java:871)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.widget.AdapterView.access$200(AdapterView.java:42)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.widget.AdapterView$SelectionNotifier.run(AdapterView.java:837)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.os.Handler.handleCallback(Handler.java:587)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.os.Handler.dispatchMessage(Handler.java:92)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.os.Looper.loop(Looper.java:130)
07-14 21:50:27.929: E/AndroidRuntime(3211): at android.app.ActivityThread.main(ActivityThread.java:3687)
07-14 21:50:27.929: E/AndroidRuntime(3211): at java.lang.reflect.Method.invokeNative(Native Method)
07-14 21:50:27.929: E/AndroidRuntime(3211): at java.lang.reflect.Method.invoke(Method.java:507)
07-14 21:50:27.929: E/AndroidRuntime(3211): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
07-14 21:50:27.929: E/AndroidRuntime(3211): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
07-14 21:50:27.929: E/AndroidRuntime(3211): at dalvik.system.NativeStart.main(Native Method)
感谢你们的任何帮助:)