簡體   English   中英

應用程序崩潰,並出現java.lang.SecurityException:權限被拒絕

[英]App crashes with java.lang.SecurityException: Permission Denial

我是新手,這個項目是我的第一個android項目。 我正在嘗試在FragmentCalls.java上顯示設備的呼叫日志。 即使在我請求運行時權限后,應用程序也會在設備上崩潰。

實際上,應用在啟動時崩潰。 請幫忙!

這是我的錯誤日志。

java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.CallLogProvider from ProcessRecord{7d3e3e4 30945:package.name.google/u0a200} (pid=30945, uid=10200) requires android.permission.READ_CALL_LOG or android.permission.WRITE_CALL_LOG

at package.name.google.fragments.FragmentCalls.getCallLogs(FragmentCalls.java:68)

at package.name.google.fragments.FragmentCalls.onCreateView(FragmentCalls.java:46)

FragmentCalls.java

package package.name.google.fragments;

import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import site.mobilesocial.google.R;
import site.mobilesocial.google.adapters.CallsRvAdapter;
import site.mobilesocial.google.models.ModelCalls;

@SuppressWarnings("WeakerAccess,FieldCanBeLocal")
public class FragmentCalls extends Fragment {
    private View v;
    private RecyclerView recyclerView;

    public FragmentCalls() {
    }

    @SuppressWarnings("UnnecessaryLocalVariable")
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        v = inflater.inflate(R.layout.frag_calls, container, false);
        recyclerView = v.findViewById(R.id.rv_calls);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        RecyclerView.LayoutManager layoutManager = linearLayoutManager;
        recyclerView.setLayoutManager(layoutManager);

       **/*This is line 46*/ CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs()); //This is line 46**
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());

        recyclerView.setAdapter(adapter);
        recyclerView.addItemDecoration(dividerItemDecoration);
        recyclerView.setHasFixedSize(true);


        return v;
    }


    @SuppressWarnings("LogNotTimber")
    private List<ModelCalls> getCallLogs() {

        List<ModelCalls> list = new ArrayList<>();

       if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.READ_CALL_LOG}, 1);
        }


      /*This is line 68*/  **Cursor cursor = getContext().getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");** //This is line 68

        assert cursor != null;
        int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
        int date = cursor.getColumnIndex(CallLog.Calls.DATE);
      //  int info = cursor.getColumnIndex(CallLog.Calls.TYPE);

        cursor.moveToNext();
        while (cursor.moveToNext()) {
            Date date1 = new Date(Long.valueOf(cursor.getString(date)));
            list.add(new ModelCalls(cursor.getString(number), date1.toLocaleString()));// cursor.getString(info)));

            Log.d("MiC:: ", cursor.getString(number));
        }
        return list;
    }
}

MainActivity.java

package package.name.google;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;
import com.mikepenz.fontawesome_typeface_library.FontAwesome;
import com.mikepenz.materialdrawer.AccountHeader;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.DrawerBuilder;
import com.mikepenz.materialdrawer.holder.BadgeStyle;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
import com.mikepenz.materialdrawer.model.SectionDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
import com.mikepenz.materialdrawer.model.interfaces.IProfile;

import java.util.HashMap;
import java.util.Objects;

import site.mobilesocial.google.adapters.ViewPagerAdapter;
import site.mobilesocial.google.fragments.FragmentCalls;
import site.mobilesocial.google.helper.DatabaseHandler;
import site.mobilesocial.google.helper.Functions;
import site.mobilesocial.google.helper.SessionManager;

@SuppressWarnings("FieldCanBeLocal")
public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private SessionManager session;
    private DatabaseHandler db;
    private AccountHeader headerResult = null;
    private Drawer result = null;
    private Toast toast = null;
    private ViewPager viewPager;
    private ProgressDialog pDialog;
    private HashMap<String,String> user = new HashMap<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = findViewById(R.id.viewpager);

        ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());

        adapter.addFragment(new FragmentCalls(), "Calls");

        viewPager.setAdapter(adapter);

        // Progress dialog
        pDialog = new ProgressDialog(this);
        pDialog.setCancelable(false);

        db = new DatabaseHandler(getApplicationContext());
        user = db.getUserDetails();


        // session manager
        session = new SessionManager(getApplicationContext());

        if (!session.isLoggedIn()) {
            logoutUser();
        }

        // Hide Keyboard
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setBackground(ContextCompat.getDrawable(getBaseContext(), R.color.md_black_1000));
      //  toolbar.setLogo(R.drawable.toolbarlogo);
            setSupportActionBar(toolbar);
            Objects.requireNonNull(getSupportActionBar()).setTitle(null);
        createAccountHeader();
        result = new DrawerBuilder(this)
                .withToolbar(toolbar)
                .withAccountHeader(headerResult)
                .withTranslucentStatusBar(true)
                .withActionBarDrawerToggle(true)
                .withActionBarDrawerToggleAnimated(true)
                .withInnerShadow(true)
                .withSliderBackgroundColor(Color.WHITE)
                .withActionBarDrawerToggle(true)
                .withTranslucentNavigationBar(true)
                .withOnDrawerListener(new Drawer.OnDrawerListener() {
                    @Override
                    public void onDrawerOpened(View drawerView) {
                        Functions.hideSoftKeyboard(MainActivity.this);
                    }

                    @Override
                    public void onDrawerClosed(View drawerView) {
                    }

                    @Override
                    public void onDrawerSlide(View drawerView, float slideOffset) {
                    }
                })

                .addDrawerItems(initDrawerItems())
                .withSavedInstance(savedInstanceState)
                .withDrawerGravity(Gravity.START)
                .addStickyDrawerItems(new SecondaryDrawerItem().withIdentifier(7).withName(R.string.logout).withIcon(FontAwesome.Icon.faw_lock).withSelectable(false))
                .withOnDrawerItemClickListener(new Drawer.OnDrawerItemClickListener() {
                    @Override
                    public boolean onItemClick(View view, int position, IDrawerItem drawerItem) {
                        if (drawerItem != null) {
                            switch ((int) drawerItem.getIdentifier()) {
                                case 7:
                                    logoutUser();
                            }
                        }
                        return false;
                    }
                })
                .build();
        result.getActionBarDrawerToggle().setDrawerIndicatorEnabled(true);

        askPermissions();

    }

   private void askPermissions() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_CALL_LOG)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CONTACTS}, 1);
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.READ_CALL_LOG}, 1);
        } else {
            finish();
        }


    }

    private void createAccountHeader() {
        user.get("name");
        user.get("email");
        headerResult = new AccountHeaderBuilder()
                .withActivity(this)
                .withTextColorRes(R.color.material_drawer_dark_header_selection_text)
                .addProfiles(
                        new ProfileDrawerItem().withIdentifier(8).withName(user.get("name")).withEmail(user.get("email"))
                )
                .withOnAccountHeaderListener(new AccountHeader.OnAccountHeaderListener() {
                    @Override
                    public boolean onProfileChanged(View view, IProfile profile, boolean current) {
                        profileClick(profile);
                        return false;
                    }
                })
                .build();
    }

    private void profileClick(IProfile profile) {
        switch ((int) profile.getIdentifier()) {
            case 8:
                toast = Toast.makeText(getApplicationContext(),
                        user.get("name"),
                        Toast.LENGTH_SHORT);
                toast.setGravity(Gravity.CENTER, 0, 0);
                toast.show();
                break;
        }
    }

    @NonNull
    private IDrawerItem[] initDrawerItems() {
        return new IDrawerItem[]{new PrimaryDrawerItem().withIdentifier(0).withName(R.string.drawer_item_home).withIcon(FontAwesome.Icon.faw_home),
                new PrimaryDrawerItem().withIdentifier(1).withName("test").withIcon(FontAwesome.Icon.faw_user_plus).withSetSelected(true),
                new PrimaryDrawerItem().withIdentifier(2).withName("test2").withIcon(FontAwesome.Icon.faw_eye).withBadge("19").withSelectable(false).withBadgeStyle(new BadgeStyle().withTextColor(Color.WHITE).withColorRes(R.color.md_red_700)),
                new SectionDrawerItem().withIdentifier(3).withName("test3"),
                new SecondaryDrawerItem().withIdentifier(4).withName("test4").withIcon(FontAwesome.Icon.faw_cogs).withSelectable(false),
                new SecondaryDrawerItem().withIdentifier(5).withName("test5").withIcon(FontAwesome.Icon.faw_asterisk).withSelectable(false),
                new SecondaryDrawerItem().withIdentifier(6).withName("test6").withIcon(FontAwesome.Icon.faw_question_circle).withSelectable(false)
        };
    }
    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState = result.saveInstanceState(outState);
        super.onSaveInstanceState(outState);
    }
    boolean doubleBackToExitPressedOnce = false;
    @Override
    public void onBackPressed() {

        if (result != null && result.isDrawerOpen()) {
            result.closeDrawer();
        } else {
            if (doubleBackToExitPressedOnce)
                super.onBackPressed();
            this.doubleBackToExitPressedOnce = true;
            Toast.makeText(this, "한번 더 누르면 종료됩니다", Toast.LENGTH_SHORT).show();

            new Handler().postDelayed(new Runnable() {

                @Override
                public void run() {
                    doubleBackToExitPressedOnce=false;
                }
            }, 2000);
        }
    }


    private void logoutUser() {
        session.setLogin(false);
        // Launching the login activity
        Functions logout = new Functions();
        logout.logoutUser(getApplicationContext());
        Intent intent = new Intent(MainActivity.this, LoginActivity.class);
        startActivity(intent);
        finish();
    }

}

權限請求的結果是異步的。 您應該在請求權限后返回該函數,並在onRequestPermissionsResult方法中執行所需的操作。

if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(getActivity(), new String[] {Manifest.permission.READ_CALL_LOG}, 1);
    return;
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    // check if permission has been granted and do your operations.
}

也不要從應該返回某些內容的方法中請求權限。 在訪問呼叫日志或其他關鍵信息之前,請確保您已經具有權限。

您可以在線找到許多有關運行時權限的教程和文檔。 官方的在這里。

如果目標版本小於23,則在清單中添加這些權限

 <uses-permission android:name="android.permission.read_contacts" />
<uses-permission android:name="android.permission.read_phone_state" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />

還檢查啟動程序活動的清單意圖過濾器,它應該存在

<intent-filter> <action android:name="android.intent.action.MAIN" /> </intent-filter>

我找到了解決方案

從我的MainActivity中刪除了askPermission(),並像這樣更改了FragmentCalls.java,這是可行的

FragmentCalls.java

package site.mobilesocial.google.fragments;

import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.CallLog;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import site.mobilesocial.google.R;
import site.mobilesocial.google.adapters.CallsRvAdapter;
import site.mobilesocial.google.models.ModelCalls;
import static android.Manifest.permission.READ_CALL_LOG;

@SuppressWarnings("WeakerAccess,FieldCanBeLocal")
public class FragmentCalls extends Fragment {
    private View v;
    private RecyclerView recyclerView;
    private static final int REQUEST_PERMISSION_CONTACTS = 1;

    public FragmentCalls() {
    }

    @SuppressWarnings("UnnecessaryLocalVariable")
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        v = inflater.inflate(R.layout.frag_calls, container, false);
        recyclerView = v.findViewById(R.id.rv_calls);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        RecyclerView.LayoutManager layoutManager = linearLayoutManager;
        recyclerView.setLayoutManager(layoutManager);

        if (ContextCompat.checkSelfPermission(getActivity(), READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED) {

            // We have access. Life is good.

            CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs());
            DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), linearLayoutManager.getOrientation());
            recyclerView.setAdapter(adapter);
            recyclerView.addItemDecoration(dividerItemDecoration);
            recyclerView.setHasFixedSize(true);



        } else if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), READ_CALL_LOG)) {

            // We've been denied once before. Explain why we need the permission, then ask again.
            Toast.makeText(getContext(), "Permission is needed", Toast.LENGTH_SHORT).show();
            requestPermissions(new String[]{READ_CALL_LOG}, REQUEST_PERMISSION_CONTACTS);

        } else {

            // We've never asked. Just do it.
            requestPermissions(new String[]{READ_CALL_LOG}, REQUEST_PERMISSION_CONTACTS);
        }
        return v;
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == REQUEST_PERMISSION_CONTACTS && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            CallsRvAdapter adapter = new CallsRvAdapter(getContext(), getCallLogs());
        } else {

            // We were not granted permission this time, so don't try to show the contact picker
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }


    @SuppressWarnings("LogNotTimber")
    private List<ModelCalls> getCallLogs() {

        List<ModelCalls> list = new ArrayList<>();
        Cursor cursor = getContext().getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, CallLog.Calls.DATE + " DESC");

        assert cursor != null;
        int number = cursor.getColumnIndex(CallLog.Calls.NUMBER);
        int date = cursor.getColumnIndex(CallLog.Calls.DATE);
      //  int info = cursor.getColumnIndex(CallLog.Calls.TYPE);

        cursor.moveToNext();
        while (cursor.moveToNext()) {
            Date date1 = new Date(Long.valueOf(cursor.getString(date)));
            list.add(new ModelCalls(cursor.getString(number), date1.toLocaleString()));// cursor.getString(info)));

            Log.d("MiC:: ", cursor.getString(number));
        }
        return list;
    }


}

就是這樣。

我也建議您嘗試一下這個庫。 Dexter是一個Android庫,可簡化運行時請求權限的過程。

https://github.com/Karumi/Dexter

樣本許可請求:

Dexter.withActivity(this)
    .withPermission(Manifest.permission.CAMERA)
    .withListener(new PermissionListener() {
        @Override public void onPermissionGranted(PermissionGrantedResponse response) {/* ... */}
        @Override public void onPermissionDenied(PermissionDeniedResponse response) {/* ... */}
        @Override public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {/* ... */}
    }).check();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM