2017-06-16 103 views
0

当我第一次启动Android应用程序时,它会触发一个对话框来询问位置权限。问题是onRequestPermissionsResult已经被触发之前我有机会按下允许或拒绝。因此,应用程序在第一次启动时没有权限,并且未设置Geofences。当然,当我重新启动应用程序时,所有权限都被授予,Geofences像他们应该那样工作。我如何在第一次启动时解决这个问题?第一次启动时的Android运行时权限

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

如何onRequestPermissionsResult()将得到无需用户交互运行时允许触发对话。尽管你可以尝试这种解决方法 - 尝试从1-2秒延迟调用方法(从你请求运行时间的权限) –

+0

他是正确的。我刚刚检查了我的geofence代码。在用户与弹出窗口交互之前,onRequestPermissionsResult不会被调用。也许发布你的整个代码 –

+0

另外,只是好奇你为什么要求所有权限?对于位置,你可以这样做 ActivityCompat.requestPermissions(this,new String [] {android.Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION); // MY_PERMISSIONS_REQUEST_LOCATION = 99; –

回答

1

的问题是,onRequestPermissionsResult之前,我不得不按alow或拒绝的机会已经被触发。

将发生的唯一方法是,如果您已授予权限,并且对话框不出现。或者,如果您决定自己拨打onRequestPermissionsResult(),这将是非常奇怪的

+0

都不是这样。我在'onRequestPermissionsResult'的开关上设置了一个断点,它在对话框显示的那一刻触发,而不是当我与它交互时触发 – Tim

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(); 
     } 
    } 
}