折线在模拟器上崩溃
Posted
技术标签:
【中文标题】折线在模拟器上崩溃【英文标题】:Polylines is crashing on emulator 【发布时间】:2020-03-25 02:50:30 【问题描述】:我正在尝试在地图上绘制折线
导入 com.google.android.gms.maps.model.Polyline; 导入 com.google.android.gms.maps.model.PolylineOptions;
导入 java.util.ArrayList; 导入 java.util.List;
公共类 MainActivity 扩展 AppCompatActivity 实现 OnMapReadyCallback、SeekBar.OnSeekBarChangeListener //初始化变量
GoogleMap gMap;
SeekBar seekWidth, seekBlue, seekGreen, seekRed;
Button btClear, btDraw;
Polyline polyline = null;
List<LatLng> latLngList = new ArrayList<>();
List<Marker> markerList = new ArrayList<>();
PolylineOptions polylineOptions = null;
int red = 0, green= 0, blue=0;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Assign variable
seekWidth = findViewById(R.id.seek_width);
seekRed = findViewById(R.id.seek_red);
seekGreen = findViewById(R.id.seek_green);
seekBlue = findViewById(R.id.seek_blue);
btDraw=findViewById(R.id.bt_draw);
btClear=findViewById(R.id.bt_clear);
/*Initialise SupportMapFragment
SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
.findFragmentById(R.id.google_map);
supportMapFragment.getMapAsync(this);
btDraw.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//Draw Polyline on Map
if (polyline!=null) polyline.remove();
//Create PolylineOptions
PolylineOptions polylineOptions = new PolylineOptions()
.addAll(latLngList).clickable(true);
polyline = gMap.addPolyline(polylineOptions);
setWidth();
);*/
//Initialise SupportMapFragment
SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
.findFragmentById(R.id.google_map);
supportMapFragment.getMapAsync(this);
btDraw.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//Draw Polyline on Map
if (polyline!=null) polyline.remove();
if(polylineOptions!=null)
//Create PolylineOptions
polyline = gMap.addPolyline(polylineOptions);
setWidth();
);
btClear.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
//Clear All
if (polyline!=null) polyline.remove();
for(Marker marker: markerList) marker.remove();
latLngList.clear();
markerList.clear();
seekWidth.setProgress(3);
seekBlue.setProgress(0);
seekGreen.setProgress(0);
seekRed.setProgress(0);
);
seekRed.setOnSeekBarChangeListener(this);
seekGreen.setOnSeekBarChangeListener(this);
seekBlue.setOnSeekBarChangeListener(this);
private void setWidth()
seekWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
//Get Seekbar Progress
int width = seekWidth.getProgress();
if (polyline != null)
//Set Polyline Width
polyline.setWidth(width);
@Override
public void onStartTrackingTouch(SeekBar seekBar)
@Override
public void onStopTrackingTouch(SeekBar seekBar)
);
/*@Override
public void onMapReady(GoogleMap googleMap)
/*gMap= googleMap;
gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
@Override
public void onMapClick(LatLng latLng)
//Create MarkerOptions
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
//Create Marker
Marker marker = gMap.addMarker(markerOptions);
//Add Latlng and Marker
latLngList.add(latLng);
markerList.add(marker);
);
*/
public void onMapReady(GoogleMap googleMap)
gMap= googleMap;
gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
@Override
public void onMapClick(LatLng latLng)
//Create MarkerOptions
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
//Create Marker
Marker marker = gMap.addMarker(markerOptions);
//Add Latlng and Marker
latLngList.add(latLng);
markerList.add(marker);
polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
);
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b)
switch (seekBar.getId())
case R.id.seek_red:
red = i;
break;
case R.id.seek_green:
green = i;
break;
case R.id.seek_blue:
blue= i;
break;
if(polyline !=null)
//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue));
@Override
public void onStartTrackingTouch(SeekBar seekBar)
@Override
public void onStopTrackingTouch(SeekBar seekBar)
错误如下:
2019-11-29 13:39:40.391 20694-20694/com.example.poly E/AndroidRuntime: 致命例外:主要 进程:com.example.poly,PID:20694 java.lang.NullPointerException:尝试调用虚拟方法 'void com.google.android.gms.maps.model.Polyline.setColor(int)' 空对象引用 在 com.example.poly.MainActivity.onProgressChanged(MainActivity.java:149) 在 android.widget.SeekBar.onProgressRefresh(SeekBar.java:93) 在 android.widget.ProgressBar.doRefreshProgress(ProgressBar.java:1327) 在 android.widget.ProgressBar.refreshProgress(ProgressBar.java:1382) 在 android.widget.ProgressBar.setProgressInternal(ProgressBar.java:1447) 在 android.widget.AbsSeekBar.trackTouchEvent(AbsSeekBar.java:850) 在 android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:760) 在 android.view.View.dispatchTouchEvent(View.java:9943) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2669) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2358) 在 com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:411) 在 com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1810) 在 android.app.Activity.dispatchTouchEvent(Activity.java:3061) 在 androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 在 com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:373) 在 android.view.View.dispatchPointerEvent(View.java:10163) 在 android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4434) 在 android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4302) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3902) 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3868) 在 android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3995) 在 android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3876) 在 android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4052) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3902) 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3868) 在 android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3876) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3849) 在 android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6210) 在 android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6184) 在 android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6145) 在 android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6313) 在 android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 在 android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(本机 方法) 在 android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176) 在 android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6284) 在 android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6336)
【问题讨论】:
您的问题标题非常糟糕,您遇到的问题与谷歌地图折线有关,我只能猜测您的地图尚未初始化,您正在尝试使用它,请更正您的标题。 感谢您的建议。我对标题进行了更改。你能告诉我如何去纠正它吗?我是 Android Studio 的初学者。 @Daiel Ravichandran 我刚刚发布了一个答案,检查一下,它应该可以解决崩溃问题,如果可以,请标记为答案。 您的折线始终为空...您在关注哪些示例?他们在哪里定义它? @Whales 感谢您的帮助。我按照您的建议进行了更改。该应用程序现在可以在模拟器上运行,但是当我在手机上安装它时会崩溃。 logcat 上的同样错误仍然出现。 【参考方案1】:这实际上可以作为临时修复或永久修复,具体取决于折线仍然为空的根本原因,但下面应该可以修复您的崩溃。
注意:我使用注释来解释下面代码的各个方面。
.
首先是在sn-p下面改:
if(polyline!=null) /*Note that without the curly brace, the if statement will only be applied to the immediate code below, so in your case, polyline is still also null here as the if statement only applies to the comment which will be ignored by the compiler. */
//Set Polyline Width
polyline.setWidth(width);
到下面:
if(polyline!=null) /*you should try and always use your opening and closing brace for readability. */
//Set Polyline Width
polyline.setWidth(width);
其次,这是您崩溃的主要原因:
//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue)); /* you for got to place a check here which is why you get the crash because as at here, *polyline* is still null for some reasons. */
所以把上面的 sn-p 改成下面的:
if(polyline !=null)
//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue));
除此之外,@cricket_007 指出:
就像上面的 Polyline polyline = null;
一样,也添加这个:PolylineOptions polylineOptions = null;
如下修改您的
SupportMapFragment
:
//Initialise SupportMapFragment
SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager()
.findFragmentById(R.id.google_map);
supportMapFragment.getMapAsync(this);
btDraw.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//Draw Polyline on Map
if (polyline!=null) polyline.remove();
if(polylineOptions!=null)
//Create PolylineOptions
polyline = gMap.addPolyline(polylineOptions);
setWidth();
);
那么这里:
@Override
public void onMapReady(GoogleMap googleMap)
gMap= googleMap;
gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
@Override
public void onMapClick(LatLng latLng)
//Create MarkerOptions
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
//Create Marker
Marker marker = gMap.addMarker(markerOptions);
//Add Latlng and Marker
latLngList.add(latLng);
markerList.add(marker);
polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
);
由于您是 android 新手,如果您发现难以找到上述代码在您的代码中的位置,请简单复制例如
polyline.setColor(Color.rgb(red,green,blue));
并导航到 AndroidStudio 中的编辑并导航到查找,将其粘贴到那里以帮助您找到代码的确切位置。 祝你编码好运。
...
新答案:
下面是完整的 java 类,包括所需的所有导入,只需复制和替换,因为它的包名相同,其他一切都相同。
package com.example.poly;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback, SeekBar.OnSeekBarChangeListener
//Initialise variables
GoogleMap gMap;
SeekBar seekWidth, seekBlue, seekGreen, seekRed;
Button btClear, btDraw;
List<LatLng> latLngList = new ArrayList<>();
List<Marker> markerList = new ArrayList<>();
int red = 0, green= 0, blue=0;
Polyline polyline = null;
PolylineOptions polylineOptions = null;
private static int PERMISSION_LOCATION_STATE = 1001; //hopefully no other permission code conflict with this in the future, so watch out.
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Assign variable
seekWidth = findViewById(R.id.seek_width);
seekRed = findViewById(R.id.seek_red);
seekGreen = findViewById(R.id.seek_green);
seekBlue = findViewById(R.id.seek_blue);
btDraw=findViewById(R.id.bt_draw);
btClear=findViewById(R.id.bt_clear);
/* We decide to put our function inside a runner that runs on UI thread to at least try to
* load the page before prompting users to allow location access, this will delay the prompt by 2 seconds.
* Note: it's actually not compulsory, so you can remove it either way, it will work.
* */
new Handler().postDelayed(new Runnable()
@Override
public void run()
mapPermissionCheck();
, 2000);
btDraw.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
//Draw Polyline on Map
if (polyline!=null) polyline.remove();
if(polylineOptions!=null)
//Create PolylineOptions
polyline = gMap.addPolyline(polylineOptions);
setWidth();
);
btClear.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
//Clear All
if (polyline!=null) polyline.remove();
for(Marker marker: markerList) marker.remove();
latLngList.clear();
markerList.clear();
seekWidth.setProgress(3);
seekBlue.setProgress(0);
seekGreen.setProgress(0);
seekRed.setProgress(0);
);
seekRed.setOnSeekBarChangeListener(this);
seekGreen.setOnSeekBarChangeListener(this);
seekBlue.setOnSeekBarChangeListener(this);
private void initSupportFragment()
SupportMapFragment supportMapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.google_map);
if(supportMapFragment!=null)
supportMapFragment.getMapAsync(this);
private void mapPermissionCheck()
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED)
//Initialise SupportMapFragment when we're sure permission is granted to access location, else Map will not be ready and mapReady() will never be called.
initSupportFragment();
else
ActivityCompat.requestPermissions(this, new String[]Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, PERMISSION_LOCATION_STATE);
private void setWidth()
seekWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
//Get Seekbar Progress
int width = seekWidth.getProgress();
if (polyline != null)
//Set Polyline Width
polyline.setWidth(width);
@Override
public void onStartTrackingTouch(SeekBar seekBar)
@Override
public void onStopTrackingTouch(SeekBar seekBar)
);
@Override
public void onMapReady(GoogleMap googleMap)
gMap= googleMap;
gMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
@Override
public void onMapClick(LatLng latLng)
//Create MarkerOptions
MarkerOptions markerOptions = new MarkerOptions().position(latLng);
//Create Marker
Marker marker = gMap.addMarker(markerOptions);
//Add Latlng and Marker
latLngList.add(latLng);
markerList.add(marker);
polylineOptions = new PolylineOptions().addAll(latLngList).clickable(true);
);
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b)
switch (seekBar.getId())
case R.id.seek_red:
red = i;
break;
case R.id.seek_green:
green = i;
break;
case R.id.seek_blue:
blue= i;
break;
if(polyline !=null)
//Set Polyline Color
polyline.setColor(Color.rgb(red,green,blue));
@Override
public void onStartTrackingTouch(SeekBar seekBar)
@Override
public void onStopTrackingTouch(SeekBar seekBar)
/*
* Right below here is a permission callback method that get called when ever an action is taken on a permission prompt request
* So, if a user declined or accept, we can check and decide what to do next, in this case, we will try enforce the user to
* give us location access in case they declined at first since we can't do much without the permission.
* */
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults)
if (requestCode == PERMISSION_LOCATION_STATE) // remember PERMISSION_LOCATION_STATE? check above on how we parse it.
if (grantResults.length > 0 && grantResults[0] != PackageManager.PERMISSION_GRANTED)
new AlertDialog.Builder(this)
.setTitle("Location Permission Needed")
.setMessage("Daniel Poly App Need Your Location Permission To Proceed.")
.setCancelable(false)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
dialog.cancel();
mapPermissionCheck();
)
.show();
else //Meaning permission finally granted....hurray!!!
initSupportFragment();
总之,你错过的是权限。 你应该read这个以获取更多信息。
【讨论】:
如何分配变量而不是检查它是否为空? @cricket_007 你是对的,所以我们可以这样: PolylineOptions polylineOptions = new PolylineOptions() .addAll(latLngList).clickable(true);折线 = gMap.addPolyline(polylineOptions);我认为这甚至应该在 onMapReady 内部以防止地图为空,无论如何,我仍然认为检查有点节省,因为它是由 onProgressChanged 确定的,我们可以知道何时调用此方法。所以check也是必要的,你说的也很重要。以上是关于折线在模拟器上崩溃的主要内容,如果未能解决你的问题,请参考以下文章