我正在尝试在地图上绘制一条折线
导入com.google.android.gms.maps.model.Polyline; 导入com.google.android.gms.maps.model.PolylineOptions;
import 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(Native 方法) 在android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176) 在android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:6284) 在android.view.ViewRootImpl $ ConsumeBatchedInputRunnable.run(ViewRootImpl.java:6336)
答案 0 :(得分:1)
实际上,这可能是临时修复或永久修复,具体取决于折线为何仍为null的根本原因,但是下面应该解决您的崩溃问题。
注意:我用注释来解释下面代码的各个方面。
。
第一件事是更改以下代码段:
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. */
因此,将上面的摘录立即更改为以下内容:
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以获取更多信息。