حذف شدن permision های برنامه در اندروید 6 + آموزش برطرف کردن این مشکل
با سلام و خسته نباشید خدمت دوستان
همونطوری که در جریانید، فقط permission تعریف کردن توی منیفست در اندروید 6 کافی نیست و در هنگام اجرا برنامه به دلیل نداشتن permision ها کرش میکنه. برای حل این مشکل باید هرزمانی که میخواستیم از یک permission استفاده کنیم اول چک کنیم که آیا کاربر دسترسی داره یا خیر. برای این موضوع چند تا از بچه ها از من سوال پرسیدن که باید همه جا همه کدهارو از اول بشینیم بنویسیم یا میشه یه بار نوشت و استفاده کرد. راه حلی که من پیشنهاد میدم به صورت زیره:
1- یک اکتیویتی parent تعریف کنید، BaseActivity و کدهای زیر رو توش قرار بدید:
package activity; import android.content.Intent; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; /** * Created by Hajhosseini on 6/7/2016. */ public class BaseActivity extends AppCompatActivity { @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); Intent intent = new Intent("PERMISSION_RECEIVER");
intent.putExtra("requestCode",requestCode); intent.putExtra("permissions",permissions); intent.putExtra("grantResults",grantResults); sendBroadcast(intent); } }
2- در مرحله دوم باید تمامی اکتیویتی هایی که درش کدهایی که از permission ها استفاده میشه رو از این اکتیویتی اکستندز کنید.
3- کلاس زیر رو توی برنامه بسازید و تمام کدها رو توش قرار بدید
package handler; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.util.Log; /** * Created by Hajhosseini on 6/6/2016. */ public class PermissionHandler { /** * Permission Sample : android.Manifest.permission.WRITE_EXTERNAL_STORAGE * String array of Permissions */ private BroadcastReceiver permissionReceiver; private OnPermissionResponse listener; private Activity activity; public void checkPermission(Activity _activity,String[] permission,OnPermissionResponse _listener) { listener = _listener; activity = _activity; if (Build.VERSION.SDK_INT >= 23) { for(int i = 0;i<permission.length;i++) { if (activity.checkSelfPermission(permission[i]) == PackageManager.PERMISSION_GRANTED) { if(i == permission.length-1) { listener.onPermissionGranted(); Log.v("TAG", "Permission is granted"); } } else { i = permission.length; registerReceiver(); ActivityCompat.requestPermissions(activity, permission, 1); Log.v("TAG", "Request permission"); } } } else { //permission is automatically granted on sdk<23 upon installation Log.v("TAG", "Permission is granted"); listener.onPermissionGranted(); } } /** * One Permission */ public void checkPermission(Activity _activity,String permission,OnPermissionResponse _listener) { listener = _listener; activity = _activity; if (Build.VERSION.SDK_INT >= 23) { if (activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) { listener.onPermissionGranted(); } else { registerReceiver(); ActivityCompat.requestPermissions(activity, new String[]{permission}, 1); } } else { //permission is automatically granted on sdk<23 upon installation Log.v("TAG", "Permission is granted"); listener.onPermissionGranted(); } } public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(grantResults[0]== PackageManager.PERMISSION_GRANTED){ // You can send your permission list or granted, but we already know what permission we need listener.onPermissionGranted(); }else { listener.onPermissionDenied(); } } public interface OnPermissionResponse{ void onPermissionGranted(); void onPermissionDenied(); } private void registerReceiver() { permissionReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { int requestCode = extras.getInt("requestCode"); String[] permissions = intent.getStringArrayExtra("permissions"); int[] grantResults = intent.getIntArrayExtra("grantResults"); onRequestPermissionsResult(requestCode,permissions,grantResults); activity.unregisterReceiver(permissionReceiver); } } }; IntentFilter localIntentFilter = new IntentFilter(); localIntentFilter.addAction("PERMISSION_RECEIVER"); activity.registerReceiver(permissionReceiver, localIntentFilter); } }
4- در مرحله آخر برای استفاده، هرجا که نیاز به گرفتن permission بود از کد زیر استفاده کنید:
توجه داشته باشید که هم میتونید 1 permission درخواست کنید، هم یک آرایه از permission ها.
new PermissionHandler().checkPermission(activity, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissionHandler.OnPermissionResponse() { @Override public void onPermissionGranted() { // permission granted // your code } @Override public void onPermissionDenied() { // User canceled permission } });
موفق باشید ;)
دوستانی که از سرویس استفاده میکنن و قصد گرفتن permission در سرویس رو دارن میتونن از کد زیر استفاده کنن:
public void checkPermission(Context _context,String permission,OnPermissionResponse _listener) { listener = _listener; context = _context; if (Build.VERSION.SDK_INT >= 23) { if (ContextCompat.checkSelfPermission(context,permission) == PackageManager.PERMISSION_GRANTED) { listener.onPermissionGranted(); } else { registerReceiver(); ActivityCompat.requestPermissions(activity, new String[]{permission}, 1); } } else { //permission is automatically granted on sdk<23 upon installation Log.v("TAG", "Permission is granted"); listener.onPermissionGranted(); } }
توی سرویس میشه فقط چک کرد آیا اپلیکیشن permission داره یا خیر، هیچ راهی نداره که بشه permission گرفت. برای دور زدن این مشکل باید یک اکتیویتی باز کنید و توی اون از کاربر اجازه دریافت permission رو بگیرید! سرویس AutoDownload روی پوش هرکس نوشته، دیگه کار نمیکنه...
از اکلیپس استفاده کردم و کتابخانه رو import کردم و مشکلی نداره ولی ....اون قسمت appcompat نیست از چندجا دانلود کردم ولی بازم همینطوری بود
اینم یه نمونه کد با ارسال آرایه ای از پرمیشن ها برای دوستان
public class ActivityMain extends ActivityBase {
private static int SECTION_COUNT;
private static String[] PERMISSIONS_SDCARD = {Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE};
public static ArrayList<StructSection> sections = new ArrayList<StructSection>();
private StructSection section;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PermissionHandler().checkPermission(ActivityMain.this,
PERMISSIONS_SDCARD, new PermissionHandler.OnPermissionResponse() {
@Override
public void onPermissionGranted() {
// permission granted
// your code
//prepareDB();
populatedFromDatabase();
}
@Override
public void onPermissionDenied() {
// User canceled permission
Toast.makeText(ActivityMain.this, R.string.conecpt_permission, Toast.LENGTH_LONG).show();
}
});
دوست گرامی میشه یک روشی بگی راحت یکجوری هست که همه برنامه های جدید اولش از آدم میپرسه دسترسی ها رو موقع ورود و دیگه هم نمیخواد. میشه اون روشو بگید چیکار کنیم ؟
به صورت ساده به این شکل میشه:
if (Build.VERSION.SDK_INT >= 23) { if (activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED) { Log.v("TAG", "Permission is granted"); } else { ActivityCompat.requestPermissions(activity, permission, 1); Log.v("TAG", "Request permission"); } } else { //permission is automatically granted on sdk<23 upon installation Log.v("TAG", "Permission is granted"); }
سلام..من کتابخونه support.v7.app.AppCompatActivity رو اضافه کردم و کلاس بیس اکتیویتی رو ساختم اما این ارورهارو میده!
فقط اینکه من از api 15 استفاده میکنم و توی support.v7.app.AppCompatActivity هم روی 15 گذاشتم ، پروژم هم روی همین نسخه ساختم
مشکل کجاست؟ و ایا باید پروژه support.v7.app.AppCompatActivity رو ببندم وقتی در پروژه ای ازش استفاده میکنم؟
دوستان باید توی گریدل خط پایین (یک ورژنش رو) ایمپورت کنید.
compile 'com.android.support:appcompat-v7:23.1.1'
در هر صورت اگر 1% هیچ راهی پیدا نکردید، میتونید از ActionbarActivity یا FragmentActivity اکستندز کنید. اگر اصن فرگمنت ندارید و نیازی به این کتابخانه هم ندارید میتونید از Activity اکستندز کنید. در هر صورت این مشکل به روش های زیادی قابل حله
سلام بر دوست عزیز
خیلی ممنون از کدی که نوشتی
برنامه من از صفحه اسکرین شات میگیره و به عنوان یه فایل jpg ذخیرش میکنه
من کدی رو که گذاشتین رو تو برنامم گذاشتم و یه مشکلی هست
اونم اینه که من وقتی برنامه رو نصب میکنم برای اولین بار از من درخواست پریمیژن رو میکنه که منم Allow رو می زنم ولی برنامه کار نمی کنه
ولی وقتی یه بار برنامه رو میبندم دوباره بازش میکنم برنامه کار میکنه میخوام ببینم دلیلش چیه !!!
فقط باید تاکید کنم فقط برای اولین بار کار نمیکنه واقعا ممنون میشم کمک کنید
public class TakeScreenshot extends AppCompatActivity {
private ScrollView vScroll;
private HorizontalScrollView hScroll;
private float mx, my;
String myDate , filename;
LayoutInflater inflater;
long num ;
File path;
File imageFile ;
FileOutputStream outputStream;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_screenshot);
vScroll = (ScrollView) findViewById(R.id.vScroll);
hScroll = (HorizontalScrollView) findViewById(R.id.hScroll);
inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
}
public void CLICK (View v){
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float curX, curY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
mx = curX;
my = curY;
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
break;
}
return true;
}
public void btnSavePDF (View v){
new MaterialDialog.Builder(this)
.title("Creating PDF")
.content("Enter file name")
.input("Example : abc", null, new MaterialDialog.InputCallback() {
@Override
public void onInput(MaterialDialog dialog, CharSequence input) {
if (input == null) {
Toast.makeText(getApplicationContext(), "Name cannot be blank", Toast.LENGTH_LONG).show();
} else {
filename = input.toString();
takeScreenshot();
}
}
})
.show();
}
private void takeScreenshot() {
Date now = new Date();
android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now);
new PermissionHandler().checkPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissionHandler.OnPermissionResponse() {
@Override
public void onPermissionGranted() {
// permission granted
path = new File(Environment.getExternalStorageDirectory(), "PICTURSSS");
if (!path.exists()) {
path.mkdir();
}
}
@Override
public void onPermissionDenied () {
// User canceled permission
}
});
try {
Bitmap bitmap = Bitmap.createBitmap(hScroll.getChildAt(0).getWidth(),
vScroll.getChildAt(0).getHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// canvas.scale(2.0f,2.0f);
hScroll.getChildAt(0).draw(canvas);
vScroll.getChildAt(0).draw(canvas);
SimpleDateFormat format= new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault());
myDate = format.format(new Date());
num = Long.parseLong(myDate);
// File imageFile = new File(path,"JPG"+num +".jpg");
new PermissionHandler().checkPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE, new PermissionHandler.OnPermissionResponse() {
@Override
public void onPermissionGranted() {
// permission granted
imageFile = new File(path,filename +".jpg");
try {
outputStream = new FileOutputStream(imageFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Override
public void onPermissionDenied () {
// User canceled permission
}
});
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
} catch (Throwable e) {
e.printStackTrace();
}
}
private void openScreenshot(File imageFile) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri uri = Uri.fromFile(imageFile);
intent.setDataAndType(uri, "image/*");
startActivity(intent);
}
}
این کدهارو هم
int quality = 100;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
outputStream.flush();
outputStream.close();
openScreenshot(imageFile);
باید توی متد onPermissionGranted بنویسید
طریقه چک پرمیشن و گرفتن پرمیشن داخل فرگمنت ها چطوره مثلا من بخوام برای فایند لوکیشن پرمیشن بگیرم به چه صورت هست ؟؟!! مثلا بخوام پرمیشن پیدا کردن مکان رو با روش شما برم جلو چیکار کنم ؟؟!
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;
public boolean checkLocationPermission(){
if (ContextCompat.checkSelfPermission(getActivity(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Asking user if explanation is needed
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(),
android.Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
//Prompt the user once explanation has been shown
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
}
return false;
} else {
return true;
}
}
چطروی با روش شما برای پرمیشن گرفتن جلو برم ؟!! ممنونم اگر کمکی کنید
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .
WRITE_EXTERNAL_STORAGE
داره. و فرض کنید که اولین اکتیویتی که توی برنامه من اجرا میشه ActivityFirst هست. حالا باید بیام توی هر 10 اکتیویتی جایی رو که پوشه ساخته میشه کدnew PermissionHandler().checkPermission
رو بنویسم و توی متدonPermissionGranted()
بگم که پوشه رو بساز یا اینکه توی ActivityFirst با کدnew PermissionHandler().checkPermission
هر پرمیشنی که نیاز داشتمو بگیرم و اگه کاربر پذیرفت دیگه موقع ساخت پوشه توی اکتیویتی های دیگه خود اندروید تشخیص میده که پرمیشن ها پذیرفته شدن؟ یه سوال دیگه: اینکه برنامه میاد از کاربر دسترسی به پرمیشن ها رو اجازه می گیره فقط یکبار اتفاق میفته یا اینکه هر بار که برنامه باز بشه این کارو میکنه؟ ممنون میشم راهنمایی کنید... (7 سال پیش)onPermissionGranted()
فقط یکبار اجرا میشه یا به تعداد پرمیشن ها؟ (7 سال پیش)