当我第一次启动Android应用程序时,它会触发一个询问位置权限的对话框。问题是在我有机会按下允许或拒绝之前onRequestPermissionsResult
已被触发。因此,应用程序在第一次启动时没有权限,并且未设置Geofences。当然,当我重新启动应用程序时,所有权限都被授予,Geofences就像他们应该的那样工作。我如何在第一次启动时解决这个问题?
public class MainActivity extends BaseActivity implements OnRetailerClickListener, NetworkListener, GoogleApiClient.ConnectionCallbacks {
public final int REQUEST_LOCATION_PERMISSION = 2222;
private GoogleApiClient googleApiClient;
private ViewPager mViewPager;
private PagerAdapter mPagerAdapter;
private OnBackPressedListener onBackPressedListener;
private List<Geofence> geofenceList;
private Intent intent;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Setup custom toolbar for viewpager layout */
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle("Overview");
setSupportActionBar(toolbar);
/* Setup TabLayout for viewpager tabs */
TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText(R.string.tab_products));
tabLayout.addTab(tabLayout.newTab().setText(R.string.tab_map));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
/* register to the geofence observer */
AppClassWiring.geofenceDao().registerObserver(this);
/* build up GoogleApiClient and connect, used to set the geofences */
googleApiClient = new GoogleApiClient
.Builder(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API).build();
googleApiClient.connect();
/* create a viewpager for the fragments */
mViewPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setOffscreenPageLimit(mPagerAdapter.getCount()); // all fragments are kept in memory because there are only 3
initViewPagerListeners(mViewPager, tabLayout);
}
@Override
protected void onResume() {
super.onResume();
if(!DeviceUtils.checkBluetooth())
askBluetooth();
}
/**
* The OnClickListener in the fragment will trigger this method.
* This way the app can switch to the correct page in the viewpager
*
* @param retailer object received from fragment
*/
@Override
public void onRetailerClick(Retailer retailer) {
mViewPager.setCurrentItem(PagerAdapter.FRAGMENT_MAP, true);
mPagerAdapter.getItemForPosition(1).onRetailerClick(retailer);
}
/**
* Init the ViewPagerListeners, used to add an onPageChangeLister for the TabLayout
* also closes the keyboard when changing pages
*
* @param viewPager instance of the used viewpager
* @param tabLayout instance of the used TabLayout above
*/
private void initViewPagerListeners(final ViewPager viewPager, TabLayout tabLayout) {
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
DeviceUtils.hideKeyboard(MainActivity.this);
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
DeviceUtils.hideKeyboard(MainActivity.this);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
/**
* Builder method to build up a Geofencingrequest with the retrieved backend data
*
* @param geofences to provide the data, required for a geofence to be built. This can be:
* an Id, Latitude, Longitude, Radius, ExpirationDuration and TransitionTypes
* @return a new instance of a GeofencingRequest
*/
private GeofencingRequest buildGeofenceRequest(List<Geofence> geofences) {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(geofences);
return builder.build();
}
@Override
public void onConnectionSuspended(int i) {
Toast.makeText(this, "Could not connect with the Google API", Toast.LENGTH_LONG).show();
}
private void askBluetooth() {
new AlertDialog.Builder(this)
.setTitle("Enable bluetooth")
.setMessage("Bluetooth should be enabled, Turn bluetooth on?")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
DeviceUtils.setBluetoothOn(true);
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
DeviceUtils.setBluetoothOn(false);
}
})
.setIcon(android.R.drawable.stat_sys_data_bluetooth)
.show();
}
/**
* When the GoogleApiClient is connected,
* the user is able to get all the geofences from the backend
*
* @param bundle null
*/
@Override
public void onConnected(@Nullable Bundle bundle) {
/* Trigger the network call to get all geofences.
The results can be shared with other classes that also listen to it */
AppClassWiring.geofenceDao().getAllGeofences();
}
/**
* Observable method that listens to the incoming results of the network call for geofences
*
* @param pointList recieved geofence/point objects from the API.
* Used to build up a GeofencingRequest. After building the GeofencingRequest,
* the data is provided to the GoogleApiClient to setup the geofences ready to trigger
*/
@Override
public void onResult(Object pointList) {
List<Point> points = (List<Point>) pointList;
geofenceList = new ArrayList<>();
for (int i = 0; i < points.size(); i++) {
geofenceList.add(new Geofence.Builder()
.setRequestId(points.get(i).getRetailer())
.setCircularRegion(
points.get(i).getValidLat(),
points.get(i).getValidLong(),
points.get(i).getValidRadius())
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER
| Geofence.GEOFENCE_TRANSITION_EXIT)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build());
}
intent = new Intent(this, GeoFencingService.class);
// Permission check
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION);
} else {
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
buildGeofenceRequest(geofenceList),
PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_LOCATION_PERMISSION: {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationServices.GeofencingApi.addGeofences(
googleApiClient,
buildGeofenceRequest(geofenceList),
PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
}
}
}
/**
* @param error provides the error that was thrown by the retrofit call.
*/
@Override
public void onError(NetworkException error) {
Toast.makeText(this, error.getMessage(), Toast.LENGTH_SHORT).show();
}
@Override
protected void onDestroy() {
onBackPressedListener = null;
/* unregister from the geofence observer */
AppClassWiring.geofenceDao().unregisterObserver(this);
super.onDestroy();
}
@Override
public void onBackPressed() {
if (onBackPressedListener != null)
onBackPressedListener.doBack();
else
super.onBackPressed();
}
public void setOnBackPressedListener(OnBackPressedListener onBackPressedListener) {
this.onBackPressedListener = onBackPressedListener;
}
}
答案 0 :(得分:1)
问题是onRequestPermissionsResult在我有机会按下或拒绝之前已经被触发。
唯一的方法是,如果您已经授予了权限,那么对话框就不会出现。或者,如果您决定自己致电onRequestPermissionsResult()
,那将非常奇怪。
答案 1 :(得分:0)
在onCreate()方法中使用此方法:
requestStoragePermission();
并在onCreate()方法之外定义此方法:
private void requestStoragePermission() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
return;
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
return;
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
return;
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)
return;
ActivityCompat.requestPermissions(this, new String[]
{
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.Manifest.permission.CAMERA,
android.Manifest.permission.READ_PHONE_STATE,
}, STORAGE_PERMISSION_CODE);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
//Checking the request code of our request
if (requestCode == STORAGE_PERMISSION_CODE) {
//If permission is granted
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//Displaying a toast
} else {
//Displaying another toast if permission is not granted
Toast.makeText(this, "Oops you just denied the permission", Toast.LENGTH_LONG).show();
}
}
}