我有一个activity,其中用户被发送到设备设置,如果GPS关闭,以打开它,当用户从设置回来,然后设备是请求位置许可。
第一个GPS对话框是通过AlertDialog builder完成的,下面是我的完整代码:
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。
我尝试取消Destroy、onPause、onpostExecute和onResume对话框,但错误仍然存在。当我按下设备GPS设置中的后退箭头,然后显示许可警报时,它显示的是准确的。
你能给我个建议,在什么地方以及如何取消那个警报窗口以避免泄漏吗?
在取消对话框后,您应该使对话框在所有地方都为null
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();
}
圣灵所结的果子,就是仁爱、喜乐、和平、忍耐、恩慈、良善、信实、温柔、节制。这样的事,没有律法禁止。凡属基督耶稣的人,是已经把肉体连肉体的邪情私欲同钉在十字架上了。我们若是靠圣灵得生,就当靠圣灵行事。不要贪图虚名,彼此惹气,互相嫉妒。(GALATIANS 5:22-26) 生成器 上节中,我们曾经做过这样的操作: >>> my_tup = (x**x for x in range(4))>>> my
1、为什么需要生成器 通过上面的学习,可以知道列表生成式,我们可以直接创建一个列表。 但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 1000 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢? 这样就不必创建完整的 li
当你需要懒惰地生成一系列的值时,考虑使用一个“生成器函数” (generator function)。Dart 对这类生成器函数有内置的支持: 同步的生成器:返回一个 Iterable 对象。 异步的生成器:返回一个 Stream 对象。 要实现一个同步的生成器函数,使用 sync* 标记函数体,并使用 yield 语句传递值: Iterable<int> naturalsTo(int n) sy
如果读过前一节,那你应该已经知道“迭代器”指的是一种可以被“for”循环使用的对象。换句话说,迭代器就是遵循迭代协议的对象。 而生成器则是迭代器的一种更为简洁的实现方法。这种写法不再需要构造一个类,而只需编写一个函数,函数每次运行到“yield”语句时都会返回一个值。下面的例子是用生成器来依次生成两个数之间的整数: def myrange(a, b): while a < b:
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。 所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循