I think my app enters loop because once it starts in device, it doesn't respond to any commands including lisener the button. I believe that the problem is the methods for permits in RunTime. I'm sorry for my English.
My code is:
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private static final int REQUEST_RESOLVE_ERROR = 3;
private GoogleApiClient mGoogleApiClient;
private volatile Location mCurrentLocation;
private static final int REQUEST_PERMISSION_LOCATE = 2;
private static final int LOCATION_DURATE_TIME = 5000;
private boolean mResolvingError = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Toast.makeText(MainActivity.this, "ciao", Toast.LENGTH_LONG).show();
}
});
}
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
Toast.makeText(MainActivity.this, "connesso", Toast.LENGTH_LONG).show();
}
#Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
manageLocationPermission();
}
#Override
public void onConnectionSuspended(int i) {
}
//gestione dell'errore
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult)
{
if (mResolvingError) {
// If we're already managing an error we skip the invocation of this method
return;
} else if (connectionResult.hasResolution()) {
// Here we check if the ConnectionResult has already the solution. If it has
// we start the resolution process
try {
// Starting resolution
mResolvingError = true;
// We launch the Intent using a request id
connectionResult.startResolutionForResult(MainActivity.this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// If we have an error during resolution we can start again.
mGoogleApiClient.connect();
}
} else {
// The ConnectionResult in the worse case has the error code we have to manage
// into a Dialog
// Starting resolution
mResolvingError = true;
}
}
//location update
private void updateLocation()
{
LocationRequest locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setNumUpdates(1)
.setExpirationDuration(LOCATION_DURATE_TIME);
LocationServices.FusedLocationApi
.requestLocationUpdates(mGoogleApiClient, locationRequest, new LocationListener() {
#Override
public void onLocationChanged(Location location)
{
mCurrentLocation = location;
}
});
}
private void startLocationListener()
{
updateLocation();
}
//permessi in RunTime
private void manageLocationPermission()
{
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED)
{
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION))
{
new AlertDialog.Builder(this)
.setTitle("Permesso di geolocalizzazione")
.setMessage("Devi dare il permesso alla geolocalizzazione")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATE);
}
})
.create()
.show();
}
else {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_PERMISSION_LOCATE);
}
}else
{
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
manageLocationPermission();
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults)
{
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == REQUEST_PERMISSION_LOCATE)
{
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
//se mi hanno accettato i permessi
startLocationListener();
}
else{
new AlertDialog.Builder(this)
.setTitle("Permesso di geolocalizzazione")
.setMessage("Devi dare il permesso alla geolocalizzazione")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.create()
.show();
}
}
}
}
If manageLocationPermission() is called with the permissions already granted, your code enters the following else clause
} else {
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
manageLocationPermission();
}
Here you're calling the same function again, and since the permissions are granted, you will enter the same else clause, and again the same thing... You see where this is going? Just remove manageLocationPermission() from this else clause
Related
I have a QR code scanner in my app and the camera stops when my AlertDialog is being displayed but restarts as soon as I move to another activity and keeps running in the background even when the app isn't in the foreground.
I have the stopCamera() and stopCameraPreview() both but it restarts and stays on as long as the app is open (both foreground and background)
Here's the code for the activity:
public class MainActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
private static final int REQUEST_CAMERA = 1;
private ZXingScannerView scannerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkPermission()) {
Toast.makeText(MainActivity.this, "Scanner Active", Toast.LENGTH_LONG).show();
} else {
requestPermission();
}
}
}
private boolean checkPermission() {
return (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED);
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{CAMERA}, REQUEST_CAMERA);
}
public void onRequestPermissionsResult(int requestCode, String[] permission, int[] grantResults) {
switch (requestCode) {
case REQUEST_CAMERA:
if (grantResults.length > 0) {
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (cameraAccepted) {
Toast.makeText(MainActivity.this, "Permission Granted!", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this, "Permission Denied", Toast.LENGTH_LONG).show();
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(CAMERA)) {
displayAlertMessage("You need to allow access for both permsisions",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{CAMERA}, REQUEST_CAMERA);
}
}
});
return;
}
}
}
break;
}
}
#Override
public void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkPermission()) {
if (scannerView == null) {
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
}
scannerView.setResultHandler(this);
scannerView.startCamera();
} else {
requestPermission();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
scannerView.stopCamera();
scannerView.stopCameraPreview();
}
public void displayAlertMessage(String message, DialogInterface.OnClickListener listener) {
new AlertDialog.Builder(MainActivity.this)
.setMessage(message)
.setPositiveButton("OK", listener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
String[] a = {"ABCD", "PQR"};
String scanned = "";
#Override
public void handleResult(Result result) {
final String scanResult = result.getText();
for (int i = 0; i < 2; i++) {
if (scanResult.equals(a[i])) {
scanned = a[i];
scannerView.stopCamera();
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("QR Scan");
builder.setMessage("Machine Identified!");
builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent1 = new Intent(MainActivity.this, buttons.class);
startActivity(intent1);
scannerView.stopCameraPreview();
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
scannerView.resumeCameraPreview(MainActivity.this);
}
});
builder.show();
break;
} else {
Toast.makeText(this, "ERROR: Unrecognized QR Code", Toast.LENGTH_LONG).show();
scannerView.resumeCameraPreview(MainActivity.this);
}
}
}
}
"keeps running in the background even when the app isn't in the foreground" - this is due to the Activity lifecycle. Note that onDestroy() is the last method of the class Activity that is called and called only when activity is for sure destroyed.
What it means: when you move to the background onDestroy() is not called. The activity is still alive and waiting to be resumed. Your activity is still alive and it should be. Use instead of onDestroy() method called onPause(). You will reach this method if the activity is killed, and it will return back to the onResume() when appropriate.
Just overwrite onDestroy() to:
#Override
public void onPause() {
super.onPause();
scannerView.stopCamera();
scannerView.stopCameraPreview();
}
this project code belongs to the project for the blinds to purchase the items. the scanresult fetch the details to the textview and reads for them and uses gesture options to handle the app.
i created the android project byr barcode scanner and output as textview and voice output. used xzing library as you can see it in the code. the problem is after showing the scanresult in plaintext, it does't atuostart the audio output functionallity. that is the real usage of this project. i referred youtube but can't. then making a chance to anyone to fix this program to text to voice.
this is my code, when working no errors at all. but no audio output after the scanresult from the barcodescanner. i tried my level best. so anyone can help out of it ??/?.
public class SecondActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler {
private static final int REQUEST_CAMERA =1;
private ZXingScannerView scannerView;
TextView result;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
Toast.makeText(SecondActivity.this, "Firebase connection is successful", Toast.LENGTH_LONG).show();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(checkPermission())
{
Toast.makeText(this, "permission is granted", Toast.LENGTH_SHORT).show();
}
else
{
requestPermission();
}
}
}
private boolean checkPermission()
{
return (ContextCompat.checkSelfPermission(SecondActivity.this, CAMERA) == PackageManager.PERMISSION_GRANTED);
}
private void requestPermission()
{
ActivityCompat.requestPermissions(this, new String[]{CAMERA}, REQUEST_CAMERA);
}
public void onRequestPermissionsResult(int requestCode, String permission[], int grantResults[])
{
switch(requestCode) {
case REQUEST_CAMERA:
if (grantResults.length > 0)
{
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if(cameraAccepted)
{
Toast.makeText(SecondActivity.this, "Permission Denied", Toast.LENGTH_LONG).show();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(shouldShowRequestPermissionRationale(CAMERA))
{
displayAlertMessage("you need to allow access for both permission",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
requestPermissions(new String[]{CAMERA}, REQUEST_CAMERA);
}
});
return;
}
}
}
}
break;
}
}
#Override
public void onResume()
{
super.onResume();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
if(checkPermission())
{
if(scannerView == null)
{
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
}
scannerView.setResultHandler(this);
scannerView.startCamera();
}
else
{
requestPermission();
}
}
}
#Override
public void onDestroy(){
super.onDestroy();
scannerView.stopCamera();
}
public void displayAlertMessage(String message, DialogInterface.OnClickListener listener)
{
new AlertDialog.Builder(SecondActivity.this)
.setMessage(message)
.setPositiveButton("OK", listener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
EditText ed1;
TextToSpeech txt;
#Override
public void handleResult(Result result) {
final String scanResult = result.getText();
setContentView(R.layout.activity_second);
final TextView text = (TextView) findViewById(R.id.editText);
/* long n=890103073;
long n1=Integer.parseInt(scanResult);
if(n1 == n)
text.setText("Pears Bathing Bar, Pure and Gentle.98% pure Glycerin & Natural Oils. Net weight 75 grams. MRP rupees 105 ");
*/
text.setText(scanResult);
scannerView.stopCamera();
txt=new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if(status!=TextToSpeech.ERROR)
{
txt.setLanguage(Locale.UK);
}
}
});
String toSpeak=ed1.getText().toString();
Toast.makeText(getApplicationContext(),toSpeak,Toast.LENGTH_SHORT).show();
txt.speak(toSpeak,TextToSpeech.QUEUE_FLUSH,null);
/* public void onPause()
{
if(txt!=null)
{
txt.stop();
txt.shutdown();
}
super.onPause();
}*/
/*AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
scannerView.resumeCameraPreview(SecondActivity.this);
}
});
builder.setNeutralButton("Visit", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_VIEW , Uri.parse(scanResult));
startActivity(intent);
}
});
builder.setMessage(scanResult);
AlertDialog alert = builder.create();
alert.show();*/
}
}
I am creating an android application and want to integrate ZXing QR Scanner. When i launch the QRScanner activity from an Intent I get the toast saying "Permission Denied, You cannot access and camera" and the app freezes instead of asking for permission for camera.
Any help to how to correctly implement permission requests or identification of any errors I looked over would be appreciated.
public class Qrscanner extends AppCompatActivity implements
ZXingScannerView.ResultHandler {
private static final int REQUEST_CAMERA = 1;
private ZXingScannerView scannerView;
private static int camId = Camera.CameraInfo.CAMERA_FACING_BACK;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
int currentApiVersion = Build.VERSION.SDK_INT;
if(currentApiVersion >= Build.VERSION_CODES.M)
{
if(checkPermission())
{
Toast.makeText(getApplicationContext(), "Permission already granted!", Toast.LENGTH_LONG).show();
}
else
{
requestPermission();
}
}
}
private boolean checkPermission()
{
return (ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA) == PackageManager.PERMISSION_GRANTED);
}
private void requestPermission()
{
ActivityCompat.requestPermissions(this, new String[]{CAMERA}, REQUEST_CAMERA);
}
#Override
public void onResume() {
super.onResume();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion >= android.os.Build.VERSION_CODES.M) {
if (checkPermission()) {
if(scannerView == null) {
scannerView = new ZXingScannerView(this);
setContentView(scannerView);
}
scannerView.setResultHandler(this);
scannerView.startCamera();
} else {
requestPermission();
}
}
}
#Override
public void onDestroy() {
super.onDestroy();
scannerView.stopCamera();
}
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
final int req = requestCode;
switch (requestCode) {
case REQUEST_CAMERA:
if (grantResults.length > 0) {
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (cameraAccepted){
Toast.makeText(getApplicationContext(), "Permission Granted, Now you can access camera", Toast.LENGTH_LONG).show();
}else {
Toast.makeText(getApplicationContext(), "Permission Denied, You cannot access and camera", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(CAMERA)) {
showMessageOKCancel("You need to allow access to both the permissions",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//
requestPermissions(new String[]{CAMERA},
//
REQUEST_CAMERA);
ActivityCompat.requestPermissions(getParent(), new String[]
{Manifest.permission.CAMERA}, req);
}
}
});
return;
}
}
}
}
break;
}
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new android.support.v7.app.AlertDialog.Builder(Qrscanner.this)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton("Cancel", null)
.create()
.show();
}
#Override
public void handleResult(final Result result) {
final String myResult = result.getText();
Log.d("QRCodeScanner", result.getText());
Log.d("QRCodeScanner", result.getBarcodeFormat().toString());
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Scan Result");
builder.setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
scannerView.resumeCameraPreview(Qrscanner.this);
}
});
builder.setNeutralButton("Confirm", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(getApplicationContext(),AddKeys.class);
intent.putExtra("publicKey",result.getText());
startActivity(intent);
}
});
builder.setMessage(result.getText());
AlertDialog alert1 = builder.create();
alert1.show();
}
}
There is a really simple solution to your problem. Inside the onCreate provide runtime permissions. I suggest you use the dexter library as it's the simplest way of implementing runtime permissions. Here is the link to the library:
https://github.com/Karumi/Dexter
I had the same problem after building your cameSource. Add this line to your code, it works for me
final String[] permissions = new String[] Manifest.permission.CAMERA};
if (!ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.CAMERA)) {
ActivityCompat.requestPermissions(MainActivity.this, permissions, RC_HANDLE_CAMERA_PERM);
}
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I am a Korean university student.
I use a translator.
Please excuse me for not being soft.
Failed to resolve issue while writing code, asking questions
Please help me.
The code below is quite simple and the only goal is to navigate from MainActivity.java to Mian2Activity.java However, I've been looking for a solution to this on a lot of tutorial and I really don't get what I'm doing wrong...
this is Main2Activity Code
public class Main2Activity extends AppCompatActivity
implements OnMapReadyCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleApiClient mGoogleApiClient = null;
private GoogleMap mGoogleMap = null;
private Marker currentMarker = null;
private static final String TAG = "googlemap_example";
private static final int GPS_ENABLE_REQUEST_CODE = 2001;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 2002;
private static final int UPDATE_INTERVAL_MS = 1000; // 1초
private static final int FASTEST_UPDATE_INTERVAL_MS = 500; // 0.5초
private AppCompatActivity mActivity;
boolean askPermissionOnceAgain = false;
boolean mRequestingLocationUpdates = false;
Location mCurrentLocatiion;
boolean mMoveMapByUser = true;
boolean mMoveMapByAPI = true;
LatLng currentPosition;
LocationRequest locationRequest = new LocationRequest()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(UPDATE_INTERVAL_MS)
.setFastestInterval(FASTEST_UPDATE_INTERVAL_MS);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_main);
Log.d(TAG, "onCreate");
mActivity = this;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient.isConnected()) {
Log.d(TAG, "onResume : call startLocationUpdates");
if (!mRequestingLocationUpdates) startLocationUpdates();
}
//앱 정보에서 퍼미션을 허가했는지를 다시 검사해봐야 한다.
if (askPermissionOnceAgain) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
askPermissionOnceAgain = false;
checkPermissions();
}
}
}
private void startLocationUpdates() {
if (!checkLocationServicesStatus()) {
Log.d(TAG, "startLocationUpdates : call showDialogForLocationServiceSetting");
showDialogForLocationServiceSetting();
}else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "startLocationUpdates : 퍼미션 안가지고 있음");
return;
}
Log.d(TAG, "startLocationUpdates : call FusedLocationApi.requestLocationUpdates");
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, locationRequest, this);
mRequestingLocationUpdates = true;
mGoogleMap.setMyLocationEnabled(true);
}
}
private void stopLocationUpdates() {
Log.d(TAG,"stopLocationUpdates : LocationServices.FusedLocationApi.removeLocationUpdates");
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mRequestingLocationUpdates = false;
}
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady :");
mGoogleMap = googleMap;
//런타임 퍼미션 요청 대화상자나 GPS 활성 요청 대화상자 보이기전에
//지도의 초기위치를 서울로 이동
setDefaultLocation();
//mGoogleMap.getUiSettings().setZoomControlsEnabled(false);
mGoogleMap.getUiSettings().setMyLocationButtonEnabled(true);
mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(15));
mGoogleMap.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener(){
#Override
public boolean onMyLocationButtonClick() {
Log.d( TAG, "onMyLocationButtonClick : 위치에 따른 카메라 이동 활성화");
mMoveMapByAPI = true;
return true;
}
});
mGoogleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
Log.d( TAG, "onMapClick :");
}
});
mGoogleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
#Override
public void onCameraMoveStarted(int i) {
if (mMoveMapByUser == true && mRequestingLocationUpdates){
Log.d(TAG, "onCameraMove : 위치에 따른 카메라 이동 비활성화");
mMoveMapByAPI = false;
}
mMoveMapByUser = true;
}
});
mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
}
});
}
#Override
public void onLocationChanged(Location location) {
currentPosition
= new LatLng( location.getLatitude(), location.getLongitude());
Log.d(TAG, "onLocationChanged : ");
String markerTitle = getCurrentAddress(currentPosition);
String markerSnippet = "위도:" + String.valueOf(location.getLatitude())
+ " 경도:" + String.valueOf(location.getLongitude());
//현재 위치에 마커 생성하고 이동
setCurrentLocation(location, markerTitle, markerSnippet);
mCurrentLocatiion = location;
}
#Override
protected void onStart() {
if(mGoogleApiClient != null && mGoogleApiClient.isConnected() == false){
Log.d(TAG, "onStart: mGoogleApiClient connect");
mGoogleApiClient.connect();
}
super.onStart();
}
#Override
protected void onStop() {
if (mRequestingLocationUpdates) {
Log.d(TAG, "onStop : call stopLocationUpdates");
stopLocationUpdates();
}
if ( mGoogleApiClient.isConnected()) {
Log.d(TAG, "onStop : mGoogleApiClient disconnect");
mGoogleApiClient.disconnect();
}
super.onStop();
}
#Override
public void onConnected(Bundle connectionHint) {
if ( mRequestingLocationUpdates == false ) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int hasFineLocationPermission = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (hasFineLocationPermission == PackageManager.PERMISSION_DENIED) {
ActivityCompat.requestPermissions(mActivity,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} else {
Log.d(TAG, "onConnected : 퍼미션 가지고 있음");
Log.d(TAG, "onConnected : call startLocationUpdates");
startLocationUpdates();
mGoogleMap.setMyLocationEnabled(true);
}
}else{
Log.d(TAG, "onConnected : call startLocationUpdates");
startLocationUpdates();
mGoogleMap.setMyLocationEnabled(true);
}
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed");
setDefaultLocation();
}
#Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "onConnectionSuspended");
if (cause == CAUSE_NETWORK_LOST)
Log.e(TAG, "onConnectionSuspended(): Google Play services " +
"connection lost. Cause: network lost.");
else if (cause == CAUSE_SERVICE_DISCONNECTED)
Log.e(TAG, "onConnectionSuspended(): Google Play services " +
"connection lost. Cause: service disconnected");
}
public String getCurrentAddress(LatLng latlng) {
//지오코더... GPS를 주소로 변환
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses;
try {
addresses = geocoder.getFromLocation(
latlng.latitude,
latlng.longitude,
1);
} catch (IOException ioException) {
//네트워크 문제
Toast.makeText(this, "지오코더 서비스 사용불가", Toast.LENGTH_LONG).show();
return "지오코더 서비스 사용불가";
} catch (IllegalArgumentException illegalArgumentException) {
Toast.makeText(this, "잘못된 GPS 좌표", Toast.LENGTH_LONG).show();
return "잘못된 GPS 좌표";
}
if (addresses == null || addresses.size() == 0) {
Toast.makeText(this, "주소 미발견", Toast.LENGTH_LONG).show();
return "주소 미발견";
} else {
Address address = addresses.get(0);
return address.getAddressLine(0).toString();
}
}
public boolean checkLocationServicesStatus() {
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|| locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
public void setCurrentLocation(Location location, String markerTitle, String markerSnippet) {
mMoveMapByUser = false;
if (currentMarker != null) currentMarker.remove();
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(currentLatLng);
markerOptions.title(markerTitle);
markerOptions.snippet(markerSnippet);
markerOptions.draggable(true);
//구글맵의 디폴트 현재 위치는 파란색 동그라미로 표시
//마커를 원하는 이미지로 변경하여 현재 위치 표시하도록 수정 fix - 2017. 11.27
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher));
currentMarker = mGoogleMap.addMarker(markerOptions);
if ( mMoveMapByAPI ) {
Log.d( TAG, "setCurrentLocation : mGoogleMap moveCamera "
+ location.getLatitude() + " " + location.getLongitude() ) ;
// CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(currentLatLng, 15);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(currentLatLng);
mGoogleMap.moveCamera(cameraUpdate);
}
}
public void setDefaultLocation() {
mMoveMapByUser = false;
//디폴트 위치, Seoul
LatLng DEFAULT_LOCATION = new LatLng(37.56, 126.97);
String markerTitle = "위치정보 가져올 수 없음";
String markerSnippet = "위치 퍼미션과 GPS 활성 요부 확인하세요";
if (currentMarker != null) currentMarker.remove();
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(DEFAULT_LOCATION);
markerOptions.title(markerTitle);
markerOptions.snippet(markerSnippet);
markerOptions.draggable(true);
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
currentMarker = mGoogleMap.addMarker(markerOptions);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(DEFAULT_LOCATION, 15);
mGoogleMap.moveCamera(cameraUpdate);
}
//여기부터는 런타임 퍼미션 처리을 위한 메소드들
#TargetApi(Build.VERSION_CODES.M)
private void checkPermissions() {
boolean fineLocationRationale = ActivityCompat
.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION);
int hasFineLocationPermission = ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION);
if (hasFineLocationPermission == PackageManager
.PERMISSION_DENIED && fineLocationRationale)
showDialogForPermission("앱을 실행하려면 퍼미션을 허가하셔야합니다.");
else if (hasFineLocationPermission
== PackageManager.PERMISSION_DENIED && !fineLocationRationale) {
showDialogForPermissionSetting("퍼미션 거부 + Don't ask again(다시 묻지 않음) " +
"체크 박스를 설정한 경우로 설정에서 퍼미션 허가해야합니다.");
} else if (hasFineLocationPermission == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "checkPermissions : 퍼미션 가지고 있음");
if ( mGoogleApiClient.isConnected() == false) {
Log.d(TAG, "checkPermissions : 퍼미션 가지고 있음");
mGoogleApiClient.connect();
}
}
}
#Override
public void onRequestPermissionsResult(int permsRequestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
if (permsRequestCode
== PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION && grantResults.length > 0) {
boolean permissionAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (permissionAccepted) {
if ( mGoogleApiClient.isConnected() == false) {
Log.d(TAG, "onRequestPermissionsResult : mGoogleApiClient connect");
mGoogleApiClient.connect();
}
} else {
checkPermissions();
}
}
}
#TargetApi(Build.VERSION_CODES.M)
private void showDialogForPermission(String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(Main2Activity.this);
builder.setTitle("알림");
builder.setMessage(msg);
builder.setCancelable(false);
builder.setPositiveButton("예", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ActivityCompat.requestPermissions(mActivity,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
});
builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
builder.create().show();
}
private void showDialogForPermissionSetting(String msg) {
AlertDialog.Builder builder = new AlertDialog.Builder(Main2Activity.this);
builder.setTitle("알림");
builder.setMessage(msg);
builder.setCancelable(true);
builder.setPositiveButton("예", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
askPermissionOnceAgain = true;
Intent myAppSettings = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
Uri.parse("package:" + mActivity.getPackageName()));
myAppSettings.addCategory(Intent.CATEGORY_DEFAULT);
myAppSettings.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mActivity.startActivity(myAppSettings);
}
});
builder.setNegativeButton("아니오", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
builder.create().show();
}
//여기부터는 GPS 활성화를 위한 메소드들
private void showDialogForLocationServiceSetting() {
AlertDialog.Builder builder = new AlertDialog.Builder(Main2Activity.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(TAG, "onActivityResult : 퍼미션 가지고 있음");
if ( mGoogleApiClient.isConnected() == false ) {
Log.d( TAG, "onActivityResult : mGoogleApiClient connect ");
mGoogleApiClient.connect();
}
return;
}
}
break;
}
}
}
and this MainActivity Code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button bttest1 = (Button)findViewById(R.id.bttest1);
bttest1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(),Main2Activity.class);
startActivity(intent);
}
});
}
}
Unable to start activity ComponentInfo{...}: java.lang.NullPointerException
An error occurs here.(Main2Activity)
mapFragment.getMapAsync(this);
What is the reason for the error?
Help me, please.
In your Main2Activity onCreate, you use setContentView(R.layout.activity_main);
It seems to be layout from MainActivity, not Main2Activity. You should make something like R.layout.activity_main2 for your second activity.
Then, your code
MapFragment mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map);
probably won't find view with ID R.id.map, because that view isn't part of first MainActivity layout.
I'm trying to get the current location using this code and it works when launching the app and when bringing it to the foreground. The toasts show up in both cases, but otherwise they don't. Can anybody tell me where I messed up?
public class LocationFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
double oldLon,oldLat;
private static final String TAG = MainActivity.class.getSimpleName(); // LogCat tag
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private static final int MY_PERMISSIONS_REQUEST_FINE_LOCATION = 100;
private Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 10000; // 10 sec
private static int FATEST_INTERVAL = 5000; // 5 sec
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// First we need to check availability of play services
if (checkPlayServices()) {
buildGoogleApiClient();
createLocationRequest();
}
}
#Override
public void onDetach() {
mCallback = null; // => avoid leaking
super.onDetach();
}
public interface InterfaceTextClicked {
public void sendText(String text);
}
private boolean checkPermission(){
if(ActivityCompat.checkSelfPermission(getContext(),
ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED){
System.out.println("We have been granted.");
return true;}
else return false;
}
private void requestPermission(){
ActivityCompat.requestPermissions(getActivity(),new String[]
{ACCESS_FINE_LOCATION},MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay!
System.out.println("Permission Granted!");
} else {
// permission denied, boo!
System.out.println("Permission Denied!");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if(shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)){
new AlertDialog.Builder(getActivity())
.setMessage("Permission needed to access your location.")
.setPositiveButton("OK", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog,int which){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermissions(new String[]{ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_FINE_LOCATION);
}
}
})
.setNegativeButton("Cancel", null)
.create()
.show();
return;
}
}
}
// return;
}
}
}
private void displayLocation(){
System.out.println("Inside displayLocation");
requestPermission();
if(checkPermission()){
mLastLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
if (mLastLocation != null) {
double latitude = mLastLocation.getLatitude();
double longitude = mLastLocation.getLongitude();
System.out.println("Location1: "+latitude+" "+longitude);
if(Double.compare(oldLat,latitude)==0 || Double.compare(oldLon,longitude)==0){
Toast.makeText(getContext(), "Location didn't change! "+latitude+ " "+ longitude,
Toast.LENGTH_LONG).show();
}else{
Toast.makeText(getContext(), "Location changed! NEW: "+latitude+ " "+ longitude+" OLD: "+oldLat+ " "+oldLon,
Toast.LENGTH_LONG).show();
}
// mCallback.sendText(latitude+" "+longitude);
oldLon = longitude;
oldLat = latitude;
} else {
System.out.println("Couldn't get coordinates");
if(mGoogleApiClient.isConnected()){
System.out.println("Client connected");
}else{
System.out.println("Client NOT connected");
}
}
}
/**
* Creating google api client object
* */
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
/**
* Method to verify google play services on the device
* */
private boolean checkPlayServices() {
GoogleApiAvailability googleAPI = GoogleApiAvailability.getInstance();
int resultCode = googleAPI.isGooglePlayServicesAvailable(getContext());
if (resultCode != ConnectionResult.SUCCESS) {
if(googleAPI.isUserResolvableError(resultCode)){
googleAPI.getErrorDialog(getActivity(),resultCode,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
getActivity().finish();
}
return false;
}
return true;
}
#Override
public void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
public void onResume() {
super.onResume();
if (mGoogleApiClient != null && !mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
checkPlayServices();
}
#Override
public void onStop() {
super.onStop();
if (mGoogleApiClient.isConnected()) {
mGoogleApiClient.disconnect();
}
}
/**
* Creating location request object
* */
protected void createLocationRequest() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FATEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); }
/**
* Starting the location updates
* */
protected void startLocationUpdates() {
System.out.println("Inside startLocationUpdates");
requestPermission();
if(checkPermission()){
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())){
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
}
}
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0){
startLocationUpdates();
// Once connected with google api, get the location
displayLocation();
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onPause() {
super.onPause();
stopLocationUpdates();
}
/**
* Stopping location updates
*/
protected void stopLocationUpdates() {
if ((mGoogleApiClient != null) && (mGoogleApiClient.isConnected())) {
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient, this);
}
}
#Override
public void onLocationChanged(Location location) {
// Assign the new location
mLastLocation = location;
Toast.makeText(getContext(), "******Location changed!",
Toast.LENGTH_SHORT).show();
// Displaying the new location on UI
displayLocation();
}
}
Sorry to put so much code up there, I thought my mistake could be anywhere so didn't want to cut out anything.
The Log shows the following:
10-14 01:10:27.408 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside startLocationUpdates
10-14 01:10:27.536 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.610 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Inside displayLocation
10-14 01:10:27.617 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: We have been granted.
10-14 01:10:27.641 14485-14485/com.android.wy.parkingauthoritytickingsystem I/System.out: Location1: 40.4868602 -74.4388156
I don't see anything obviously wrong with your code, though it is making its API calls through the deprecated versions of the location APIs rather than the new FusedLocationProviderClient interface.
While you declare a new-style FusedLocationProviderClient:
private FusedLocationProviderClient mFusedLocationClient;
you never initialize it or use it at runtime; rather you call through FusedLocationApi (the old method):
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
You might try using the new API, which has a slightly more robust interface, to shed some light on your problem. You can get the new API interface with:
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
Then you'll just need to tweak your class to add an onLocationAvailability callback as per the documentation before attaching your listener:
mFusedLocationClient.requestLocationUpdates(mLocationRequest,
mLocationCallback,
null /* Looper */);