如何避免应用程序在启动时询问权限?

How to avoid app asking permission on launch?

以下是我在我的应用程序中需要的权限。

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

我的主Activity

`public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
//Binding Views
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.app_bar)
AppBarLayout mAppBarLayout;
@BindView(R.id.ntb_horizontal)
NavigationTabBar mBottomNavigationBar;
@BindView(R.id.vp_horizontal_ntb)
ViewPager mViewPager;
@BindView(R.id.drawer_layout)
DrawerLayout mDrawer;
@BindView(R.id.drawerIcon)
ImageView drawerIcon;
@BindView(R.id.nav_view)
ArcNavigationView mArcNav;
@BindView(R.id.appName)
TextView appName;
boolean doubleBackToExitPressedOnce = false;
@BindView(R.id.searchIcon)
ImageView search;
//Initialization of Classes
SessionManager session;
ApiClient apiClient;
PersonalDetail personalDetail;
//Properties to access
Context context;
public CircleImageView userImageDrawer;
TextView userNameDrawer;
String email, access_token;
boolean showNotificationBadge;
String notificationBadge = "NOT SET";
List<OrgAccount> accountList = new ArrayList<>();
private File outPutFile = null;
private Uri mImageCaptureUri;
Feeds_Fragment feedsFragment = new Feeds_Fragment();
boolean initialCall = true;
GoogleSignInClient mgoogleSignInClient;
private GoogleApiClient mGoogleApiClient;

//For Device Contacts
private static final int PERMISSIONS_REQUEST_READ_CONTACTS = 100;



    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    session = new SessionManager(this);
    if (session.isLoggedIn()) {
        Log.d("Am in Main", "Activity Session Checked " + session.isLoggedIn());
        session.checkLogin();
    } else {
        ButterKnife.bind(this);
        context = this;
        Common.initializeSubjects();
        HashMap<String, String> user = session.getUserDetails();
        email = user.get(SessionManager.KEY_EMAIL);
        access_token = user.get(SessionManager.KEY_ACCESS_TOKEN);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawer, mToolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        mDrawer.addDrawerListener(toggle);
        toggle.syncState();
        toggle.setDrawerIndicatorEnabled(false);
        toggle.setDrawerSlideAnimationEnabled(false);
        mArcNav.setNavigationItemSelectedListener(this);
        mViewPager.setOffscreenPageLimit(4);
        mViewPager.setCurrentItem(0);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setHomeButtonEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        drawerIcon.setOnClickListener(v -> mDrawer.openDrawer(GravityCompat.START));
        initStatusBar();
        setNavigationTabBar();
        getKeyboardStatus();
        handleClicks();

    }


}

private void handleClicks() {

    search.setOnClickListener(v -> {
        Intent intent = new Intent(MainActivity.this, SearchNew.class);
        startActivity(intent);
        overridePendingTransition(R.anim.slide_up, R.anim.anim_dismiss);
    });
}



public void getKeyboardStatus() {
    Keyboardutils.addKeyboardToggleListener((Activity) context, new Keyboardutils.SoftKeyboardToggleListener() {
        @Override
        public void onToggleSoftKeyboard(boolean isVisible) {
            Log.d("keyboard", "keyboard visible: " + isVisible);
        }
    });
}

private void initStatusBar() {

    Window window = getWindow();


    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
            Window w = getWindow(); // in Activity's onCreate() for instance
            w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP || Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
            setTheme(R.style.AppTheme_NoActionBarHello);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            SystemBarTintManager tintManager = new SystemBarTintManager(this);
            tintManager.setStatusBarTintEnabled(true);
            tintManager.setTintColor(ContextCompat.getColor(this, R.color.white));
        }
  //         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && 
  Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
  //            
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  //            SystemBarTintManager tintManager = new 
  SystemBarTintManager(this);
  //            tintManager.setStatusBarTintEnabled(true);
  //            tintManager.setTintColor(ContextCompat.getColor(this, 
  R.color.white));
  //        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Log.d("This is diplay", " AM inside Oreo Version");
            window.setNavigationBarColor(ContextCompat.getColor(this, 
  R.color.white));

        }

    }

public void switchFragment(int target) {
    mViewPager.setCurrentItem(target);
}






private void setNavigationTabBar() {
    mViewPager.setAdapter(new 
  FragmentPagerAdapter(getSupportFragmentManager()) {
        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return feedsFragment;
                case 1:
                    return new Suggestion_Fragment();
                case 2:
                    return new Write_Review_Fragment();
                case 3:
                    return new Notifications_Fragment();
                case 4:
                    return new User_Profile_Fragment();
                default:
                    return new Feeds_Fragment();
            }
        }

        @Override
        public int getCount() {
            return 5;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return "page" + position;
        }
    });
    final String[] colorsForNavigationBar = this.getResources().getStringArray(R.array.navigation_bar_colors);
    final ArrayList<NavigationTabBar.Model> models = new ArrayList<>();


    models.add(new NavigationTabBar.Model.Builder(
            getResources().getDrawable(R.drawable.rating_feed),
            Color.parseColor(colorsForNavigationBar[0]))
            .title("Feeds")
            .build());
    models.add(new NavigationTabBar.Model.Builder(
            getResources().getDrawable(R.drawable.conn),
            Color.parseColor(colorsForNavigationBar[0]))
            .title("SeatMates")
            .build());
    models.add(new NavigationTabBar.Model.Builder(
            getResources().getDrawable(R.drawable.review_one),
            Color.parseColor(colorsForNavigationBar[0]))
            .title("Write Review")
            .build());
    models.add(new NavigationTabBar.Model.Builder(
            getResources().getDrawable(R.drawable.notification),
            Color.parseColor(colorsForNavigationBar[0]))
            .title("Notifications")
            .build());
    models.add(new NavigationTabBar.Model.Builder(
            getResources().getDrawable(R.drawable.user_one),
            Color.parseColor(colorsForNavigationBar[0]))
            .title("Profile")
            .build());

    mBottomNavigationBar.setViewPager(mViewPager, 0);
    mBottomNavigationBar.canScrollHorizontally(-1);
    mBottomNavigationBar.setTitleSize(10 * getResources().getDisplayMetrics().density);
    mBottomNavigationBar.setBehaviorEnabled(false);
    mBottomNavigationBar.setModels(models);
    mViewPager.getChildCount();
    //TODO:Important Code for hiding the padding
    mBottomNavigationBar.post(() -> {
        final View viewPager = findViewById(R.id.vp_horizontal_ntb);
        ((ViewGroup.MarginLayoutParams) viewPager.getLayoutParams()).bottomMargin =
                (int) 0;
        viewPager.requestLayout();
    });
    mBottomNavigationBar.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
            if (position == 3 || position == 2) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mAppBarLayout.setElevation(0f);
                }
            } else if (position == 0 || position == 1 || position == 4) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
                        ) {
                    mAppBarLayout.setElevation(3f);
                }
            }
        }

        @Override
        public void onPageSelected(final int position) {
            mBottomNavigationBar.getModels().get(position).hideBadge();
        }

        @Override
        public void onPageScrollStateChanged(final int state) {

        }
    });
}

@Override
public void onResume() {
    super.onResume();
}

@Override
public void onBackPressed() {
    if (mViewPager.getCurrentItem() != 0) {
        mViewPager.setCurrentItem(0);
    } else if (mViewPager.getCurrentItem() == 0 && feedsFragment.scrollOutItem > 3) {
        feedsFragment.smoothScrollToPosition();
    } else {
        super.onBackPressed();
    }
}

@Override
public void onDestroy() {
    finish();
    super.onDestroy();
}


@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.logOut) {
        logOut();
    } else if (id == R.id.all_reviews) {
        Intent intent = new Intent(context, AllReviews.class);
        intent.putExtra("WHERE", "nothing");
        mDrawer.closeDrawer(GravityCompat.START);
        startActivity(intent);
    } else if (id == R.id.app_new_setting) {
        openSettingsActivity();
    } else if (id == R.id.nav_manageSeatmate) {
        openManageSeatMateActivity();
    } else if (id == R.id.nav_experience) {
        openExperiencesActivity();
    } else if (id == R.id.nav_invites) {
        openAllInvitesActivity();
    } else if (id == R.id.nav_mySkills) {
        openAllSkillsActivity();
    } else if (id == R.id.nav_organization) {
        openOrganizationActivity();
    } else if (id == R.id.nav_projects) {
        openProjectsActivity();
    }

    return true;
}



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    for (Fragment fragment : getSupportFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

private void showError(Throwable e) {
    String message = "";
    try {
        if (e instanceof IOException) {
            message = "No internet connection!";
        } else if (e instanceof HttpException) {
            HttpException error = (HttpException) e;
            String errorBody = error.response().errorBody().string();
            JSONObject jObj = new JSONObject(errorBody);
            message = jObj.getString("error");
        }
    } catch (IOException e1) {
        e1.printStackTrace();
    } catch (JSONException e1) {
        e1.printStackTrace();
    } catch (Exception e1) {
        e1.printStackTrace();
    }
    if (TextUtils.isEmpty(message)) {
        message = "Unknown error occurred! Check LogCat.";
    }
    Snackbar snackbar = Snackbar.make(mDrawer, message, Snackbar.LENGTH_LONG);
    View sbView = snackbar.getView();
    TextView textView = sbView.findViewById(android.support.design.R.id.snackbar_text);
    textView.setTextColor(Color.YELLOW);
    snackbar.show();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            ///--

        } else {
            Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
        }
    }
}


}`

在我的 MainActiviy 中,我没有任何需要访问外部存储的权限,但在应用程序启动时它仍然要求访问媒体、照片等的权限。

那么我怎样才能避免启动时出现权限对话框并在需要时弹出呢。例如:更新个人资料照片时。

是否与会话或共享偏好有关?

我还认为我的应用程序在提示权限时崩溃了。

以下是崩溃后的logcat。

`    java.lang.IllegalArgumentException: width and height must be > 0
    at android.graphics.Bitmap.createBitmap(Bitmap.java:1039)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:1006)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:956)
    at android.graphics.Bitmap.createBitmap(Bitmap.java:917)
    at devlight.io.library.ntb.NavigationTabBar.onDraw(NavigationTabBar.java:1077)
    at android.view.View.draw(View.java:19200)
    at android.view.View.buildDrawingCacheImpl(View.java:18448)
    at android.view.View.buildDrawingCache(View.java:18308)
    at android.view.View.draw(View.java:18920)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.draw(View.java:19203)
    at android.view.View.updateDisplayListIfDirty(View.java:18150)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.support.constraint.ConstraintLayout.dispatchDraw(ConstraintLayout.java:2023)
    at android.view.View.updateDisplayListIfDirty(View.java:18141)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.support.design.widget.CoordinatorLayout.drawChild(CoordinatorLayout.java:1254)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.draw(View.java:19203)
    at android.view.View.updateDisplayListIfDirty(View.java:18150)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.support.v4.widget.DrawerLayout.drawChild(DrawerLayout.java:1366)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.draw(View.java:19203)
    at android.view.View.updateDisplayListIfDirty(View.java:18150)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.updateDisplayListIfDirty(View.java:18141)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.updateDisplayListIfDirty(View.java:18141)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.updateDisplayListIfDirty(View.java:18141)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.updateDisplayListIfDirty(View.java:18141)
    at android.view.View.draw(View.java:18928)
    at android.view.ViewGroup.drawChild(ViewGroup.java:4240)
    at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4026)
    at android.view.View.draw(View.java:19203)
    at com.android.internal.policy.DecorView.draw(DecorView.java:817)
    at android.view.View.updateDisplayListIfDirty(View.java:18150)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:669)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:675)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:783)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:3020)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2834)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2387)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1420)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6835)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
    at android.view.Choreographer.doCallbacks(Choreographer.java:723)
    at android.view.Choreographer.doFrame(Choreographer.java:658)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
2018-10-17 15:18:07.709 E/AndroidRuntime:     at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6647)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
2018-10-17 15:18:07.712 V/FA: Connection attempt already in progress
2018-10-17 15:18:07.713 V/FA: Connection attempt already in progress
2018-10-17 15:18:07.713 V/FA: Activity resumed, time: 181047867
2018-10-17 15:18:07.716 V/FA: Screen exposed for less than 1000 ms. Event not sent. time: 45
2018-10-17 15:18:07.717 V/FA: Connection attempt already in progress
2018-10-17 15:18:07.717 V/FA: Activity paused, time: 181047884
2018-10-17 15:18:12.015 E/CrashlyticsCore: Failed to execute task.
    java.util.concurrent.TimeoutException
        at java.util.concurrent.FutureTask.get(FutureTask.java:206)
        at com.crashlytics.android.core.CrashlyticsBackgroundWorker.submitAndWait(CrashlyticsBackgroundWorker.java:41)
        at com.crashlytics.android.core.CrashlyticsController.handleUncaughtException(CrashlyticsController.java:321)
        at com.crashlytics.android.core.CrashlyticsController.onUncaughtException(CrashlyticsController.java:301)
        at com.crashlytics.android.core.CrashlyticsUncaughtExceptionHandler.uncaughtException(CrashlyticsUncaughtExceptionHandler.java:42)
        at com.instabug.crash.a.uncaughtException(InstabugUncaughtExceptionHandler.java:116)
        at com.instabug.library.a.a.uncaughtException(InstabugUncaughtExceptionHandler.java:28)
        at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
        at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1063)
        at java.lang.Thread.dispatchUncaughtException(Thread.java:1955)`

目前正在奥利奥上进行测试。

就我而言,我正在处理一个库,即 Instabug,它请求允许存储和共享应用程序的屏幕截图以报告错误。

将此添加为答案,以便其他人也可以通过这种方式进行挖掘。我希望这会对某人有所帮助。