应用程序在按下开始按钮时显示ANR(App Not Responding)对话框。 这个应用程序的动机是找到大约使用或电话行进的距离。我没有使用时钟,但只是检查应用程序是否正常工作 提前致谢
Java代码
package com.skydiver.distancecalculator;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Locale;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
//Objects to access the sensors in the device
Sensor accelero ;
SensorManager manager;
float currentAcc, lastAcc=0.0f, effectiveAcc;
float distance = 0, totalDistance = 0;
int time_elapsed = 0;
//Text fields to show the value of acceleration,time and distance travelled
TextView accX, accY, accZ, dist_total, dist_last, time;
//Variables to store the value of acceleration in X,Y and Z directions
public float val_accX, val_accY, val_accZ;
//Buttons for starting and stopping the distance Calculations
Button startButton, stopButton, resetButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Binding Button in the java code with the layout widgets
startButton = (Button) findViewById(R.id.start);
stopButton = (Button) findViewById(R.id.stop);
resetButton =(Button) findViewById(R.id.reset);
//Getting the Sensor service using sensor manager object to access the accelerometer sensor in device
manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelero = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//Check if there is an accelerometer sensor present on the Device
if(accelero == null){
//Displays a message to the user that sensor is not present
Toast.makeText(getApplicationContext(), "Sensor Not Present on Device", Toast.LENGTH_SHORT).show();
}
//Registering the sensor manager to listen to the sensor events at 10ms
manager.registerListener(this, accelero, 10000);
//Binding Textviews in the java code with the layout widgets
accX = (TextView) findViewById(R.id.text_accX);
accY = (TextView) findViewById(R.id.text_accY);
accZ = (TextView) findViewById(R.id.text_accZ);
time = (TextView) findViewById(R.id.text_time);
dist_last = (TextView) findViewById(R.id.text_last_dist);
dist_total = (TextView) findViewById(R.id.text_total_dist);
//Setting the function on click action of buttons
resetButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
resetFields();
}
});
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
resetFields();
calculate();
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopCalculation();
}
});
}
@Override
protected void onPause(){
//Unregister the listener if the user moves to another activity or app
manager.unregisterListener(this);
super.onPause();
}
@Override
protected void onResume(){
//Resume the listener on resuming of the activity
manager.registerListener(this,accelero, 10000);
super.onResume();
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
//Getting the changed values of the sensors in the variables
val_accX = sensorEvent.values[0];
val_accY = sensorEvent.values[1];
val_accZ = sensorEvent.values[2];
//Calling the function to calculate the total distance travelled
calculate();
//Display the current acceleration values to the user
displayValues();
}
public void calculate() {
while (true){
currentAcc = (float) Math.sqrt(Math.pow(val_accZ,2)+Math.pow(val_accZ,2)+Math.pow(val_accZ,2) - Math.pow(9.80665,2));
effectiveAcc = currentAcc - lastAcc;
distance = Math.abs(effectiveAcc) * 0.5f * time_elapsed * time_elapsed ;
totalDistance += distance;
lastAcc = currentAcc;
time_elapsed +=1;
if (stopButton.isPressed()) {
break;
}
}
}
private void stopCalculation(){
dist_total.setText(String.format("Total Distance: " + "%s" + " m", Float.toString(totalDistance)));
//time.setText(String.format(Locale.getDefault(),"Time: " + "%d" + " s", time_elapsed));
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
public void resetFields(){
time.setText(R.string.time_0_0);
dist_last.setText(R.string.distance_0_0);
dist_total.setText(R.string.total_distance_0_0);
}
public void displayValues(){
accX.setText(String.format("Acceleration X: " + "%s" , val_accX));
accY.setText(String.format("Acceleration Y: " + "%s" , val_accY));
accZ.setText(String.format("Acceleration Z: " + "%s" , val_accZ));
}
}
XML File
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.skydiver.distancecalculator.MainActivity"
android:orientation="vertical">
<TextView
android:text="@string/acceleration_x_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_accX" />
<TextView
android:text="@string/acceleration_y_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_accY" />
<TextView
android:text="@string/acceleration_z_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_accZ" />
<TextView
android:text="@string/time_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_time" />
<TextView
android:text="@string/distance_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_last_dist" />
<TextView
android:text="@string/total_distance_0_0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:padding="3dp"
android:layout_margin="3dp"
android:gravity="start"
android:layout_gravity="center_horizontal"
android:id="@+id/text_total_dist" />
<LinearLayout
android:orientation="horizontal"
android:layout_margin="5dp"
android:padding="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/start"
android:text="@string/start"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
<Button
android:id="@+id/stop"
android:text="@string/stop"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp" />
</LinearLayout>
<Button
android:id="@+id/reset"
android:text="@string/reset_fields"
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.skydiver.distancecalculator" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
答案 0 :(得分:1)
删除while (true) {
行和相应的右括号。每次传感器更新时,您只需要循环内容执行一次。
同样删除这些行,因为只有当用户在执行时按下停止按钮时,此if
语句才会为真:
if (stopButton.isPressed()) {
break;
}
除非您在运行计算之外需要传感器值,否则应等到按下开始按钮后才能调用SensorManager.registerListener()
,并且在按下停止按钮时应调用SensorManager.unregisterListener()
(这就是为什么你不需要上面的if
声明。否则,当您不需要传感器值并且运行加速度计时,您将接收传感器值。
答案 1 :(得分:0)
要扩展@ Karakuri的答案:传感器事件在主线程中进入。您打算快速处理它们并将控制权返回给操作系统。通过永久循环,您可以防止主线程做任何事情,包括响应Android生命周期事件,重绘或处理下一个传感器事件。你最终会被一个看门狗定时器杀死,它会查找UI线程卡住并杀死应用程序的情况。
您需要重新架构您的应用。没有循环。如果要停止响应事件,请从中取消注册。如果您想再次开始收听,请重新注册。