Android Studio:应用在某些手机上崩溃

4
我是一名新手安卓开发者,对于这个问题感到非常困惑。我正在制作一个简单的应用程序,其中有3个 TextViews:text、text2 和 text3。
- text 显示用户的纬度 - text2 显示用户的经度 - text3 显示用户与名为 "Azadi Square" 的地方之间的距离
该应用程序在三星 Galaxy S4 和三星 Galaxy Tab S 上正常运行,但在华为 Y511 和某些索尼 Xperia(我不知道确切的名称)上无法打开,并显示“应用程序已停止工作”的消息。
下面是我的 Java 代码:
public class Map extends Activity implements LocationListener {

private TextView text,text2,text3;
private String provider;
private LocationManager locationManager;
private double latitude,longitude;
private Location azadiSquare;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);

    text = (TextView)findViewById(R.id.text);
    text2 = (TextView)findViewById(R.id.text2);
    text3 = (TextView)findViewById(R.id.text3);

    locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);

    Criteria criteria = new Criteria();
    provider = locationManager.getBestProvider(criteria,false);

    azadiSquare = new Location(provider);
    azadiSquare.setLatitude(35.6996540);
    azadiSquare.setLongitude(51.3379906);

    Location location = locationManager.getLastKnownLocation(provider);


    text.setText(location.getLatitude()+"");
    text2.setText(location.getLongitude()+"");
    text3.setText(distanceBetweenMeter(azadiSquare,location)+"");
}

@Override
protected void onResume() {
    super.onResume();

    locationManager.requestLocationUpdates(provider,400,1,this);
}

@Override
protected void onPause() {
    super.onPause();

    locationManager.removeUpdates(this);
}

@Override
public void onLocationChanged(Location location) {
    latitude = location.getLatitude();
    longitude = location.getLongitude();

    text.setText(latitude+"");
    text2.setText(longitude+"");

    text3.setText(distanceBetweenMeter(azadiSquare,location)+"");
}

@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
    // TODO Auto-generated method stub
}

@Override
public void onProviderEnabled(String s) {
    Toast.makeText(this,"Enabled new provider " + provider,Toast.LENGTH_LONG).show();
}

@Override
public void onProviderDisabled(String s) {
    Toast.makeText(this,"Disabled provider " + provider,Toast.LENGTH_LONG).show();
}


private double getDistanceFromLatLonInKm(double lat1,double lon1,double lat2,double lon2) {
    double R = 6371; // Radius of the earth in km
    double dLat = deg2rad(lat2-lat1);  // deg2rad below
    double dLon = deg2rad(lon2-lon1);
    double a =
            Math.sin(dLat/2) * Math.sin(dLat/2) +
                    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
                            Math.sin(dLon/2) * Math.sin(dLon/2)
            ;
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double d = R * c; // Distance in km
    return d;
}

private double deg2rad(double deg) {
    return deg * (Math.PI/180);
}

private int distanceBetweenMeter(Location location1, Location location2){
    double distanceKM = getDistanceFromLatLonInKm(location1.getLatitude(),location1.getLongitude(),
            location2.getLatitude(),location2.getLongitude());
    int distanceMeter = (int)(distanceKM*1000);
    return distanceMeter;
}
}

注意:我刚刚删除了导入项!

清单文件:

<?xml version="1.0" encoding="utf-8"?>

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".Map" android:screenOrientation="landscape">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

注意:我在打开应用前已经打开了手机的定位功能,所以这不是问题。另外我想说的是所有计算都没有问题,它们都能正常工作。


当屏幕上出现“不幸停止”消息时,必须有一些日志。在华为y511或索尼Xperia上以调试模式运行应用程序并获取日志。编辑您的原始问题并粘贴错误信息。 - ᴛʜᴇᴘᴀᴛᴇʟ
你能分享一下你的应用程序 build.gradle 文件吗? - Ankit Mehta
4个回答

3
在 Android 6.0(API 级别 23)及更高版本中,您需要在运行时请求 ACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION 权限。请参见“在运行时请求权限”。可能会出现这种情况。

谢谢您的快速回答。但是我提到的所有手机都装有Android 4或5 ... - M.Nik

1

最好的做法是记录下问题并回溯,这样您就可以看到出了什么问题或至少有一个线索。如果用户35603的答案没有起作用,请尝试此方法并发布与您的问题相关的logcat部分。


谢谢您的回答。我该如何在手机上使用logcat?我想我应该说我构建了apk并将其安装在手机上。所以我不知道如何使用logcat... - M.Nik
展示这个最好的方式是在stackoverflow上查看这些有用的链接:如果你还没有安装ADB驱动程序,那么你需要安装它们,但我假设你已经安装了它们,因为你有Android Studio: http://forum.xda-developers.com/showthread.php?p=48915118然后进入目录或者如果已经设置了路径,则使用CMD并跟随谷歌上的链接来使用ADB。 https://developer.android.com/studio/command-line/logcat.html - Winston Jasaragic
如果你在我的第一条评论之后还是不理解,这个教程可能会帮助你更好地理解,因为stackoverflow不允许过长和详细的故事:http://forum.xda-developers.com/showthread.php?t=2141817 - Winston Jasaragic
其实我知道如何使用ADB,但问题是ADB没有位置信息。这会造成任何问题吗? - M.Nik
它不会造成任何问题,因为adb只是作为手机和电脑之间的桥梁使用。如果您成功进行日志记录,您将看到与位置相关的问题出现在哪里。祝你好运! - Winston Jasaragic

0

终于问题解决了!代码的这一部分一直在制造麻烦:

Location location = locationManager.getLastKnownLocation(provider);

text.setText(location.getLatitude()+"");
text2.setText(location.getLongitude()+"");

我猜需要一点时间才能获取当前位置 location 。实际上,当应用程序想运行下面这行代码时,位置仍然为空,导致应用程序崩溃:
text1.setText(location.getLatitude()+"");

我用类似这样的方法解决了崩溃问题:

Location location = locationManager.getLastKnownLocation(provider);

while(location==null){}

text.setText(location.getLatitude()+"");
text2.setText(location.getLongitude() + "");
text3.setText(distanceBetweenMeter(azadiSquare,location)+"");

崩溃问题已经解决,但是应用程序在白屏状态下卡住了。我不确定具体原因,但我猜测可能是陷入了while循环中。谢谢!


0
public class MainActivity extends AppCompatActivity {

pb=findViewById(R.id.progressbar);
Example ex=new Example();//The subclass object is created here
boolean stop=false;//a boolean variable to start or stop the thread to get location. 
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (location== null) {
        showSettingDialog();//this will show your custom way of displaying 
                              //the location setting intent
        new Thread(ex).start();//here the fetching location gets started
    }
    else{
       //here write code after your location is fetched
       //here to got some other base activity or stay in this
        finish();//if you wan to stay in this activity then omit this line.
    }
}

public class Example implements Runnable{ //This is a sub class in your main activity.

    @Override
    public void run() {//overriding run medthod
            try {

                while(location==null) { //this part keeps on running whithout 
                                         //ui freeze
                     if (stop) {
                        return;
                    }
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            pb.setVisibility(View.VISIBLE);
                        }
                    });

                    getLastLocation();//this function will fetch location.
                    Thread.sleep(1500);
                    pb.setVisibility(View.INVISIBLE);
                    if (location != null) {
                        //do your code here
                        stop = true;
                        finish();
                    }
                }
            }


             catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }

            }

        }

1
请解释您的答案,而不仅仅是发布代码片段。其他用户应该能够从您的答案中学习。 - david
嘿,David!这里的问题是当你的位置未开启或由于低GPS信号而无法获取位置时。为了避免这个问题,只需在UI线程中让你的应用程序显示一些进度条,并在后台线程中使用while状态语句来获取位置,这样UI就不会看起来像被冻结了,同时你也可以在后台线程中获取位置。 - Ananthula Saikowshik
很好,但请尝试以更详细的方式更新您的答案。谢谢! - david

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接