2017-06-16 105 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(); 
     } 
    } 
}