카카오 api를 이용한 지도 앱을 실행시키면 강제 종료가 됩니다.

조회수 1424회

/////////////////////Logcat

06-10 16:18:29.638 5991-5991/com.example.bencall E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.bencall, PID: 5991 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.bencall/com.example.bencall.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void net.daum.mf.map.api.MapView.setCurrentLocationEventListener(net.daum.mf.map.api.MapView$CurrentLocationEventListener)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) at android.app.ActivityThread.access$800(ActivityThread.java:144) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5221) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void net.daum.mf.map.api.MapView.setCurrentLocationEventListener(net.daum.mf.map.api.MapView$CurrentLocationEventListener)' on a null object reference at com.example.bencall.MapsActivity.onCreate(MapsActivity.java:44) at android.app.Activity.performCreate(Activity.java:5937) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)  at android.app.ActivityThread.access$800(ActivityThread.java:144)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)  at android.os.Handler.dispatchMessage(Handler.java:102)  at android.os.Looper.loop(Looper.java:135)  at android.app.ActivityThread.main(ActivityThread.java:5221)  at java.lang.reflect.Method.invoke(Native Method)  at java.lang.reflect.Method.invoke(Method.java:372)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////MapsActivity.java//////////////////////////////////////////////////////////

public class MapsActivity extends AppCompatActivity implements MapView.CurrentLocationEventListener, MapReverseGeoCoder.ReverseGeoCodingResultListener {

private static final String LOG_TAG = "MainActivity";

private MapView mMapView;


private static final int GPS_ENABLE_REQUEST_CODE = 2001;
private static final int PERMISSIONS_REQUEST_CODE = 100;
String[] REQUIRED_PERMISSIONS  = {Manifest.permission.ACCESS_FINE_LOCATION};




@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    mMapView = (MapView) findViewById(R.id.map_view);
    //mMapView.setDaumMapApiKey(MapApiConst.DAUM_MAPS_ANDROID_APP_API_KEY);
    mMapView.setCurrentLocationEventListener(this);

    if (!checkLocationServicesStatus()) {

        showDialogForLocationServiceSetting();
    }else {

        checkRunTimePermission();
    }

}

@Override
protected void onDestroy() {
    super.onDestroy();
    mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOff);
    mMapView.setShowCurrentLocationMarker(false);
}

@Override
public void onCurrentLocationUpdate(MapView mapView, MapPoint currentLocation, float accuracyInMeters) {
    MapPoint.GeoCoordinate mapPointGeo = currentLocation.getMapPointGeoCoord();
    Log.i(LOG_TAG, String.format("MapView onCurrentLocationUpdate (%f,%f) accuracy (%f)", mapPointGeo.latitude, mapPointGeo.longitude, accuracyInMeters));
}


@Override
public void onCurrentLocationDeviceHeadingUpdate(MapView mapView, float v) {

}

@Override
public void onCurrentLocationUpdateFailed(MapView mapView) {

}

@Override
public void onCurrentLocationUpdateCancelled(MapView mapView) {

}

@Override
public void onReverseGeoCoderFoundAddress(MapReverseGeoCoder mapReverseGeoCoder, String s) {
    mapReverseGeoCoder.toString();
    onFinishReverseGeoCoding(s);
}

@Override
public void onReverseGeoCoderFailedToFindAddress(MapReverseGeoCoder mapReverseGeoCoder) {
    onFinishReverseGeoCoding("Fail");
}

private void onFinishReverseGeoCoding(String result) {

// Toast.makeText(LocationDemoActivity.this, "Reverse Geo-coding : " + result, Toast.LENGTH_SHORT).show(); }

/*
 * ActivityCompat.requestPermissions를 사용한 퍼미션 요청의 결과를 리턴받는 메소드입니다.
 */
@Override
public void onRequestPermissionsResult(int permsRequestCode,
                                       @NonNull String[] permissions,
                                       @NonNull int[] grandResults) {

    if ( permsRequestCode == PERMISSIONS_REQUEST_CODE && grandResults.length == REQUIRED_PERMISSIONS.length) {

        // 요청 코드가 PERMISSIONS_REQUEST_CODE 이고, 요청한 퍼미션 개수만큼 수신되었다면

        boolean check_result = true;


        // 모든 퍼미션을 허용했는지 체크합니다.

        for (int result : grandResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                check_result = false;
                break;
            }
        }


        if ( check_result ) {
            Log.d("@@@", "start");
            //위치 값을 가져올 수 있음
            mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithHeading);
        }
        else {
            // 거부한 퍼미션이 있다면 앱을 사용할 수 없는 이유를 설명해주고 앱을 종료합니다.2 가지 경우가 있습니다.

            if (ActivityCompat.shouldShowRequestPermissionRationale(this, REQUIRED_PERMISSIONS[0])) {

                Toast.makeText(MapsActivity.this, "퍼미션이 거부되었습니다. 앱을 다시 실행하여 퍼미션을 허용해주세요.", Toast.LENGTH_LONG).show();
                finish();


            }else {

                Toast.makeText(MapsActivity.this, "퍼미션이 거부되었습니다. 설정(앱 정보)에서 퍼미션을 허용해야 합니다. ", Toast.LENGTH_LONG).show();

            }
        }

    }
}

void checkRunTimePermission(){

    //런타임 퍼미션 처리
    // 1. 위치 퍼미션을 가지고 있는지 체크합니다.
    int hasFineLocationPermission = ContextCompat.checkSelfPermission(MapsActivity.this,
            Manifest.permission.ACCESS_FINE_LOCATION);


    if (hasFineLocationPermission == PackageManager.PERMISSION_GRANTED ) {

        // 2. 이미 퍼미션을 가지고 있다면
        // ( 안드로이드 6.0 이하 버전은 런타임 퍼미션이 필요없기 때문에 이미 허용된 걸로 인식합니다.)


        // 3.  위치 값을 가져올 수 있음
        mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithHeading);


    } else {  //2. 퍼미션 요청을 허용한 적이 없다면 퍼미션 요청이 필요합니다. 2가지 경우(3-1, 4-1)가 있습니다.

        // 3-1. 사용자가 퍼미션 거부를 한 적이 있는 경우에는
        if (ActivityCompat.shouldShowRequestPermissionRationale(MapsActivity.this, REQUIRED_PERMISSIONS[0])) {

            // 3-2. 요청을 진행하기 전에 사용자가에게 퍼미션이 필요한 이유를 설명해줄 필요가 있습니다.
            Toast.makeText(MapsActivity.this, "이 앱을 실행하려면 위치 접근 권한이 필요합니다.", Toast.LENGTH_LONG).show();
            // 3-3. 사용자게에 퍼미션 요청을 합니다. 요청 결과는 onRequestPermissionResult에서 수신됩니다.
            ActivityCompat.requestPermissions(MapsActivity.this, REQUIRED_PERMISSIONS,
                    PERMISSIONS_REQUEST_CODE);


        } else {
            // 4-1. 사용자가 퍼미션 거부를 한 적이 없는 경우에는 퍼미션 요청을 바로 합니다.
            // 요청 결과는 onRequestPermissionResult에서 수신됩니다.
            ActivityCompat.requestPermissions(MapsActivity.this, REQUIRED_PERMISSIONS,
                    PERMISSIONS_REQUEST_CODE);
        }

    }

}



//여기부터는 GPS 활성화를 위한 메소드들
private void showDialogForLocationServiceSetting() {

    AlertDialog.Builder builder = new AlertDialog.Builder(MapsActivity.this);
    builder.setTitle("위치 서비스 비활성화");
    builder.setMessage("앱을 사용하기 위해서는 위치 서비스가 필요합니다.\n"
            + "위치 설정을 수정하실래요?");
    builder.setCancelable(true);
    builder.setPositiveButton("설정", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
            Intent callGPSSettingIntent
                    = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(callGPSSettingIntent, GPS_ENABLE_REQUEST_CODE);
        }
    });
    builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int id) {
            dialog.cancel();
        }
    });
    builder.create().show();
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {

        case GPS_ENABLE_REQUEST_CODE:

            //사용자가 GPS 활성 시켰는지 검사
            if (checkLocationServicesStatus()) {
                if (checkLocationServicesStatus()) {

                    Log.d("@@@", "onActivityResult : GPS 활성화 되있음");
                    checkRunTimePermission();
                    return;
                }
            }

            break;
    }
}

public boolean checkLocationServicesStatus() {
    LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

    return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
            || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}

}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////activity_maps.xml//////////////////////////////////////////////////////////

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

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="194dp"
    android:layout_weight="8"
    android:orientation="vertical">


    <EditText
        android:id="@+id/start"
        android:layout_width="320dp"
        android:layout_height="wrap_content"
        android:hint="출발지" />

    <EditText
        android:id="@+id/goal"
        android:layout_width="320dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/start"
        android:hint="도착지" />

    <Button
        android:id="@+id/search1"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_marginTop="5dp"
        android:layout_toRightOf="@+id/start"
        android:background="#f8dd43"
        android:text="검색" />

    <Button
        android:id="@+id/search2"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_below="@+id/search1"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@+id/goal"
        android:background="#f8dd43"
        android:text="검색" />


    <Button
        android:id="@+id/call"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/goal"
        android:layout_marginTop="5dp"
        android:background="#f8dd43"
        android:text="call" />

    <Button
        android:id="@+id/cancel"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_below="@+id/goal"
        android:layout_toRightOf="@+id/call"
        android:layout_marginLeft="15dp"
        android:layout_marginTop="5dp"
        android:background="#f8dd43"
        android:text="취소" />


</RelativeLayout>



<net.daum.mf.map.api.MapView
    android:id="@+id/map_view"
    android:layout_width="match_parent"
    android:layout_height="550dp" />

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)