我有一个活动,如果GPS处于关闭状态以将其打开,则将用户发送到设备设置,并且当用户从设置返回时,则设备正在请求位置许可。
因此,第一个GPS对话框是通过AlertDialog构建器完成的,这是我的完整代码:
public class Okoli extends AppCompatActivity implements LocationListener {
private final static int ALL_PERMISSIONS_RESULT = 101;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1;
private static final long MIN_TIME_BW_UPDATES = 90000; //1.5 mins
LocationManager locationManager;
Location loc;
ArrayList<String> permissions = new ArrayList<>();
ArrayList<String> permissionsToRequest= new ArrayList<>();
ArrayList<String> permissionsRejected = new ArrayList<>();
boolean isGPS = false;
boolean isNetwork = false;
boolean canGetLocation = true;
ArrayList<Actors> actorsList;
ActorAdapterDist adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(getSupportActionBar() != null){
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setTitle((Html.fromHtml("<font color=\"#c6c6c6\">V okolí (vzdušná čiara)</font>")));
getSupportActionBar().setHomeAsUpIndicator(R.drawable.back);
}
setContentView(R.layout.okoli_fragment);
actorsList = new ArrayList<>();
adapter = new ActorAdapterDist(this, R.layout.okoli_item, actorsList);
TextView listTitle = findViewById(R.id.booklist_title1);
listTitle.setText("Čakám na signál GPS");
getIntent().setAction("created");
String MY_PREFS_NAME = "resumecheck";
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putInt("idName", 2);
editor.apply();
ListView lv = findViewById(R.id.listViewx); lv.setAdapter(adapter);
locationManager = (LocationManager) this.getSystemService(Service.LOCATION_SERVICE);
assert locationManager != null;
isGPS = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetwork = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
permissionsToRequest = findUnAskedPermissions(permissions);
if (!isGPS && !isNetwork) {
showSettingsAlert(getString(R.string.askgps), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (dialog != null) {
dialog.dismiss(); dialog = null;
}
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});
getLastLocation();
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (permissionsToRequest.size() > 0) {
requestPermissions(permissionsToRequest.toArray(new String[permissionsToRequest.size()]),
ALL_PERMISSIONS_RESULT);
canGetLocation = false;
}
}
getLocation();
}
}
@Override
public void onLocationChanged(Location location) {updateUI(location);}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {}
@Override
public void onProviderEnabled(String s) {
getLocation();
}
@Override
public void onProviderDisabled(String s) {
if (locationManager != null) {
locationManager.removeUpdates(this);
}
}
private void getLocation() { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
try {
if (canGetLocation) {
if (isGPS) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else if (isNetwork) {
// from Network Provider
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
loc = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if (loc != null) {updateUI(loc);}
}
} else {
loc.setLatitude(0);
loc.setLongitude(0);
updateUI(loc);
}
} else {
Toast.makeText(this, R.string.nolocation,
Toast.LENGTH_LONG).show();
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
private void getLastLocation() {
try {
Criteria criteria = new Criteria();
String provider = locationManager.getBestProvider(criteria, false);
if(provider==null) { showSettingsAlert(getString(R.string.askgps), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});}
else {
Location location = locationManager.getLastKnownLocation(provider);
if (location != null) {updateUI(location);}
}
} catch (SecurityException e) {
e.printStackTrace();
}
}
private ArrayList findUnAskedPermissions(ArrayList<String> wanted) {
ArrayList<String> result = new ArrayList<>();
for (String perm : wanted) {
if (!hasPermission(perm)) {
result.add(perm);
}
}
return result;
}
private boolean hasPermission(String permission) {
if (canAskPermission()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return (this.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED);
}
}
return true;
}
private boolean canAskPermission() {
return (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1);
}
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case ALL_PERMISSIONS_RESULT:
for (String perms : permissionsToRequest) {
if (!hasPermission(perms)) {
permissionsRejected.add(perms);
}
}
if (permissionsRejected.size() > 0) {//Log.e("rejected", "onRequestPermissionsResult");
String MY_PREFS_NAME = "resumecheck";
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putInt("idName", 2);
editor.apply();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(permissionsRejected.get(0))) {
editor.putInt("idName", 1);
editor.apply();
showMessageOKCancel(getString(R.string.denied),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissionsRejected.toArray(
new String[permissionsRejected.size()]), ALL_PERMISSIONS_RESULT);
}
}
});
return;
}
}
} else {
// Log.e("ON", "No rejected permissions.");
String MY_PREFS_NAME = "resumecheck";
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putInt("idName", 2);
editor.apply();
canGetLocation = true;
getLocation();
}
break;
}
}
public void showSettingsAlert(String message, DialogInterface.OnClickListener okListener) {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert);
builder.setTitle(R.string.nogps);
builder.setMessage(message);
builder.setPositiveButton(R.string.ano, okListener);
builder.setNegativeButton(R.string.nie, null);
builder.create();
builder.show();
}
private void showMessageOKCancel(String message, DialogInterface.OnClickListener okListener) {
new AlertDialog.Builder(this, R.style.Theme_AppCompat_Dialog_Alert)
.setMessage(message)
.setPositiveButton("OK", okListener)
.setNegativeButton(R.string.cancel, null)
.create()
.show();
}
public void updateUI(Location loc) {
double Act1=loc.getLatitude();
double Act2=loc.getLongitude();
adapter.clear();adapter.notifyDataSetChanged();
TextView listTitle = findViewById(R.id.booklist_title1);
ListView lv = findViewById(R.id.listViewx);
if (Act1 > 0.0) { listTitle.setVisibility(View.GONE);lv.setVisibility(View.VISIBLE);GetContacts task = new GetContacts (Act1, Act2);
task.execute();
// new GetContacts().execute(Act1,Act2);
} else {
listTitle.setVisibility(View.VISIBLE);listTitle.setText("Čakám na signál GPS");lv.setVisibility(View.GONE);
}
}
ProgressDialog dialog;
@Override
public void onDestroy() {
super.onDestroy();
if (locationManager != null) {
locationManager.removeUpdates(this);
}
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
}
@Override
protected void onPause() {
super.onPause();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
}
class GetContacts extends AsyncTask<Double, Void, Boolean> {
private Double act1;
private Double act2;
GetContacts(double act1, double act2) {
this.act1 = act1;
this.act2 = act2;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(Okoli.this);
dialog.setMessage("Načítavam");
dialog.setTitle("Pripájam sa k serveru");
dialog.show();
dialog.setCancelable(false);
dialog.dismiss();
dialog=null;
}
@Override
protected Boolean doInBackground(Double... args) {
HttpHandler sh = new HttpHandler();
String url = "https://www.hrady-zamky.sk/app/premium_feed.php?i=7&search=";
String jsonStr = sh.makeServiceCall(url);
int pocet =0;
if (jsonStr != null) {
try {JSONObject jsonObj = new JSONObject(jsonStr);
JSONArray actors = jsonObj.getJSONArray("result");
double myDistx;
//Log.e("pocet",String.format("value = %d", actors.length()));
for (int i = 0; i < actors.length(); i++) {
JSONObject c = actors.getJSONObject(i);
Actors actor = new Actors();
double g1 = Double.parseDouble(c.getString("gps1"));
double g2 = Double.parseDouble(c.getString("gps2"));
myDistx = calculateDistance(act1, act2, g1, g2);
if (myDistx <= 50) {
actor.setLetter("x");
actor.setNazov(c.getString("nazov"));
actor.setThumb(c.getString("thumb"));
actor.setPerex(c.getString("perex"));
actor.setTyp(c.getString("typ"));
actor.setPlace(c.getString("place"));
actor.setGps1(c.getString("gps1"));
actor.setGps2(c.getString("gps2"));
actor.setExterier(c.getString("adresar"));
actor.setDist(myDistx);
actorsList.add(actor);
pocet++;
}
}
if (pocet == 0) {
runOnUiThread(new Runnable() {
public void run() {
Toast.makeText(Okoli.this.getApplicationContext(), R.string.nothing_around, Toast.LENGTH_LONG).show();
}
});
}
Collections.sort(actorsList, new Comparator<Actors>() {
@Override
public int compare(Actors lhs, Actors rhs) {
return lhs.getDist().compareTo(rhs.getDist());
}
});
} catch (final JSONException e) {
Okoli.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(Okoli.this.getApplicationContext(),
"Chyba dát: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}); }
return true;
} else {
Okoli.this.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(Okoli.this.getApplicationContext(),
"Chyba internetového pripojenia.",
Toast.LENGTH_LONG).show();
}
});
return false;
}
}
final static double AVERAGE_RADIUS_OF_EARTH = 6371;
double calculateDistance(double userLat, double userLng, double venueLat, double venueLng) {
double latDistance = Math.toRadians(userLat - venueLat);
double lngDistance = Math.toRadians(userLng - venueLng);
double a = (Math.sin(latDistance / 2) * Math.sin(latDistance / 2)) +
(Math.cos(Math.toRadians(userLat))) *
(Math.cos(Math.toRadians(venueLat))) *
(Math.sin(lngDistance / 2)) *
(Math.sin(lngDistance / 2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (AVERAGE_RADIUS_OF_EARTH * c);
}
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (dialog != null && dialog.isShowing()) {
dialog.dismiss(); dialog = null;
}
//dialog.dismiss();
adapter.notifyDataSetChanged();
}
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() { //restart activity after back from GPS settings
super.onResume();
adapter.clear();
adapter.notifyDataSetChanged();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
String action = getIntent().getAction();
// Prevent endless loop by adding a unique action, don't restart if action is present
if(action == null || !action.equals("created")) {
String MY_PREFS_NAME = "resumecheck";
SharedPreferences prefs = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE);
int idName = prefs.getInt("idName", 0); //0 is the default value.
if(idName == 2) {
Intent intent = new Intent(this, Okoli.class);
startActivity(intent);
finish();
} else {
SharedPreferences.Editor editor = getSharedPreferences(MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putInt("idName", 1);
editor.apply(); }
}
// Remove the unique action so the next time onResume is called it will restart
else
getIntent().setAction(null);
}
}
但是它可以正常工作,但是控制台给我一个错误
android.view.WindowLeaked: Activity sk.hrady_zamky.darksymphony.hrady_zamkypremium.Okoli has leaked window DecorView@11bd862[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:576)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:363)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:128)
at android.app.Dialog.show(Dialog.java:454)
at android.support.v7.app.AlertDialog$Builder.show(AlertDialog.java:1006)
at **sk.hrady_zamky.Okoli.showSettingsAlert(Okoli.java:298)
at sk.hrady_zamky.Okoli.onCreate(Okoli.java:95)**
at android.app.Activity.performCreate(Activity.java:7372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
第95和298行指向showSettingsAlert。
我试图关闭onDestroy,onPause,onpostExecute和onResume对话框,但是错误仍然存在。当我按设备GPS设置中的后退箭头,然后又显示权限警报时,该窗口正好显示。
能否请您提供建议,在何处以及如何关闭该警报窗口以避免泄漏?
答案 0 :(得分:0)
关闭对话框后,所有位置都应使对话框为空
if (dialog != null)
{
dialog.dismiss();
dialog = null;
}
所以您的onDestroy应该是
@Override
public void onDestroy() {
super.onDestroy();
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
}
像这样更改您的showSettingsAlert方法
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setTitle("GPS is not Enabled!");
alertDialog.setMessage("Do you want to turn on GPS?");
alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
});
alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
alertDialog.show();
}
答案 1 :(得分:0)
好的,我想我已经在onResume中找到了问题。我先进行了startActivity然后完成,所以大概应该先完成然后再进行startActivity。
但是现在我像这样更新了onResume:
if (Okoli.isFromSetting){
if (dialog != null) {
dialog.dismiss();
dialog = null;
}
startActivity(getIntent());
Okoli.isFromSetting=false;
所以我在对话框中使用isFromSetting true并检查其状态以避免活动的无限循环重启。
但是我认为通过删除finish()并仅保留startActivity可以解决该问题。
似乎它现在可以正常运行了,没有任何错误或异常。