如果您想了解android–与FileProvider共享文件时使用grantUriPermission的SecurityException和android共享文件夹的知识,那么本篇文章将是您的不二之
如果您想了解android – 与FileProvider共享文件时使用grantUriPermission的SecurityException和android 共享文件夹的知识,那么本篇文章将是您的不二之选。我们将深入剖析android – 与FileProvider共享文件时使用grantUriPermission的SecurityException的各个方面,并为您解答android 共享文件夹的疑在这篇文章中,我们将为您介绍android – 与FileProvider共享文件时使用grantUriPermission的SecurityException的相关知识,同时也会详细的解释android 共享文件夹的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- android – 与FileProvider共享文件时使用grantUriPermission的SecurityException(android 共享文件夹)
- Android 9.0 自动更新 安装包解析错误 java.lang.SecurityException: Permission Denial
- Android getActiveNotifications抛出SecurityException
- Android lollipop java.lang.SecurityException:用户和当前进程都没有android.permission.BLUETOOTH_PRIVILEGED
- Android M 6.0 – SecurityException试图删除帐户
android – 与FileProvider共享文件时使用grantUriPermission的SecurityException(android 共享文件夹)
我有两个申请.我正在尝试使用FileProvider将应用程序A中的文件共享到应用程序B.应用程序A在应用程序B中的ContentProvider上调用insert方法以插入记录.插入的数据包括我想要从App A共享的文件的Uri.App B中的ContentProvider将尝试从App A读取共享文件.
由于我没有使用Intent来共享文件,因此我在App A中调用Context.grantUriPermission以允许读取(并且有时写入):
mContext.grantUriPermission(MyPackageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
但是,执行此行会给我(名称已更改以保护无辜者):
java.lang.SecurityException: Uid 10066 does not have permission to uri content://au.com.example.AppA.fileprovider/MyFolder/MyFileName
at android.os.Parcel.readException(Parcel.java:1322)
at android.os.Parcel.readException(Parcel.java:1276)
at android.app.ActivityManagerProxy.grantUriPermission(ActivityManagerNative.java:2374)
at android.app.ContextImpl.grantUriPermission(ContextImpl.java:1371)
at android.content.Contextwrapper.grantUriPermission(Contextwrapper.java:400)
at etc...
应用程序A在清单文件中具有以下内容:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="au.com.example.AppA.fileprovider"
android:exported="false"
android:grantUriPermissions="true"
android:readPermission="au.com.example.READ_CONTENT"
android:writePermission="au.com.example.WRITE_CONTENT" >
<Meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
filepaths.xml有:
<paths>
<files-path
name="MyFolder"
path="MyFolder/" />
</paths>
App A和App B都有以下内容:
<uses-permission android:name="au.com.example.READ_CONTENT" />
<uses-permission android:name="au.com.example.WRITE_CONTENT" />
我已经尝试在两个应用中定义权限.它们都使用相同的调试签名进行签名:
<permission
android:name="au.com.example.READ_CONTENT"
android:permissionGroup="MyGroup"
android:protectionLevel="signature" >
</permission>
<permission
android:name="au.com.example.WRITE_CONTENT"
android:permissionGroup="MyGroup"
android:protectionLevel="signature" >
</permission>
文件最终的实际路径是:
/data/data/au.com.example.AppA/files/MyFolder
在这一点上,我很难过.我不知道为什么我不能授予我刚在同一个应用程序中创建的文件的权限.所以我的问题是:为什么我会收到此异常,如何成功授予App B权限?
解决方法:
好吧,经过一周和大量的试验和错误,似乎答案是不指定权限.所以App A Manifest应该包含:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="au.com.example.AppA.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<Meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
即,我删除了读写权限.我最初的理解,并没有找到其他说明的文件,这些是限制访问的必要条件.但是,我发现它们确实会干扰并导致Context.grantUriPermission失败.访问权限已经有限.
为了完成图片,并回答我的问题的第二部分,我发现了以下内容:
Android Permission denial in Widget RemoteViewsFactory for Content
我不得不补充:
final long token = Binder.clearCallingIdentity();
try {
[retrieve file here]
} finally {
Binder.restoreCallingIdentity(token);
}
到App B中的Content Provider.否则它也会出现安全错误.
Android 9.0 自动更新 安装包解析错误 java.lang.SecurityException: Permission Denial
在 android 9.0 自动下载更新时 遇到 安装包解析错误
在 android 7.0 使用的是同一套框架却没有问题?
然后通过 adb 命令抓取一下异常发现
12-18 19:21:32.665 4804 5604 W InstallStaging: java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.***.***.update_app.file_provider/download/update/***.apk from pid=4804, uid=1000 requires the provider be exported, or grantUriPermission()
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.os.Parcel.createException(Parcel.java:1950)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.os.Parcel.readException(Parcel.java:1918)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:698)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1459)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1296)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.content.ContentResolver.openInputStream(ContentResolver.java:1016)
12-18 19:21:32.665 4804 5604 W InstallStaging: at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:167)
12-18 19:21:32.665 4804 5604 W InstallStaging: at com.android.packageinstaller.InstallStaging$StagingAsyncTask.doInBackground(InstallStaging.java:160)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.os.AsyncTask$2.call(AsyncTask.java:333)
12-18 19:21:32.665 4804 5604 W InstallStaging: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
12-18 19:21:32.665 4804 5604 W InstallStaging: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)
12-18 19:21:32.665 4804 5604 W InstallStaging: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
12-18 19:21:32.665 4804 5604 W InstallStaging: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
12-18 19:21:32.665 4804 5604 W InstallStaging: at java.lang.Thread.run(Thread.java:764)
发现 Android9.0 是需要权限读取 fileProvider 和 uri 的
于是我看了一下三方框架的源码,确实没有加权限
private Intent installIntent(Context context, String path) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_DEFAULT);
String fileProviderAuthority = getFileProviderAuthority(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && null!= fileProviderAuthority) {
Uri fileUri = FileProvider.getUriForFile(context, fileProviderAuthority, new File(path));
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
}
return intent;
}
于是我就扒了一下源码对其进行修改
private Intent installIntent(Context context, String path) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_DEFAULT);
String fileProviderAuthority = getFileProviderAuthority(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && null!= fileProviderAuthority) {
Uri fileUri = FileProvider.getUriForFile(context, fileProviderAuthority, new File(path));
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
grantUriPermission(getPackageName(), fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
}
return intent;
}
测试通过,完美安装,没有出现解析失败问题
代码:
<!--AndroidManifest.xml-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="包名.file_provider"
android:exported="false"
android:grantUriPermissions="true">
<!-- 元数据 -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"
tools:replace="android:resource" />
</provider>
<service android:name=".UpdateService"/>//从源码下载的升级下载安装apk的服务
<!-- file_paths.xml -->
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path path="." name="download" />
<external-cache-path
name="storage/emulated/0"
path="." />
</paths>
/**
* Created by Sun on 2020/12/19.
*/
public class UpdateService extends Service {
public static final String TAG = "UpdateService";
public static final String ACTION = "me.shenfan.UPDATE_APP";
public static final String STATUS = "status";
public static final String PROGRESS = "progress";
public static boolean DEBUG = false;
//下载大小通知频率
public static final int UPDATE_NUMBER_SIZE = 1;
public static final int DEFAULT_RES_ID = -1;
public static final int UPDATE_PROGRESS_STATUS = 0;
public static final int UPDATE_ERROR_STATUS = -1;
public static final int UPDATE_SUCCESS_STATUS = 1;
//params
private static final String URL = "downloadUrl";
private static final String ICO_RES_ID = "icoResId";
private static final String ICO_SMALL_RES_ID = "icoSmallResId";
private static final String UPDATE_PROGRESS = "updateProgress";
private static final String STORE_DIR = "storeDir";
private static final String DOWNLOAD_NOTIFICATION_FLAG = "downloadNotificationFlag";
private static final String DOWNLOAD_SUCCESS_NOTIFICATION_FLAG = "downloadSuccessNotificationFlag";
private static final String DOWNLOAD_ERROR_NOTIFICATION_FLAG = "downloadErrorNotificationFlag";
private static final String IS_SEND_BROADCAST = "isSendBroadcast";
private String downloadUrl;
private int icoResId; //default app ico
private int icoSmallResId;
private int updateProgress; //update notification progress when it add number
private String storeDir; //default sdcard/Android/package/update
private int downloadNotificationFlag;
private int downloadSuccessNotificationFlag;
private int downloadErrorNotificationFlag;
private boolean isSendBroadcast;
private UpdateProgressListener updateProgressListener;
private LocalBinder localBinder = new LocalBinder();
/**
* Class used for the client Binder.
*/
public class LocalBinder extends Binder {
/**
* set update progress call back
*
* @param listener
*/
public void setUpdateProgressListener(UpdateProgressListener listener) {
UpdateService.this.setUpdateProgressListener(listener);
}
}
private boolean startDownload;//开始下载
private int lastProgressNumber;
private NotificationCompat.Builder builder;
private NotificationManager manager;
private int notifyId;
private String appName;
private LocalBroadcastManager localBroadcastManager;
private Intent localIntent;
private DownloadApk downloadApkTask;
/**
* whether debug
*/
public static void debug() {
DEBUG = true;
}
private Intent installIntent(Context context, String path) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addCategory(Intent.CATEGORY_DEFAULT);
String fileProviderAuthority = getFileProviderAuthority(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && null!= fileProviderAuthority) {
Uri fileUri = FileProvider.getUriForFile(context, fileProviderAuthority, new File(path));
intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
grantUriPermission(getPackageName(), fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
} else {
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive");
}
return intent;
}
/**
* 获取FileProvider的auth
*/
private static String getFileProviderAuthority(Context context) {
try {
for (ProviderInfo provider : context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_PROVIDERS).providers) {
if (FileProvider.class.getName().equals(provider.name) && provider.authority.endsWith(".update_app.file_provider")) {
return provider.authority;
}
}
} catch (PackageManager.NameNotFoundException ignore) {
}
return null;
}
private static Intent webLauncher(String downloadUrl) {
Uri download = Uri.parse(downloadUrl);
Intent intent = new Intent(Intent.ACTION_VIEW, download);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
private static String getSaveFileName(String downloadUrl) {
if (downloadUrl == null || TextUtils.isEmpty(downloadUrl)) {
return System.currentTimeMillis() + ".apk";
}
return downloadUrl.substring(downloadUrl.lastIndexOf("/"));
}
private static File getDownloadDir(UpdateService service) {
File downloadDir = null;
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
if (service.storeDir != null) {
downloadDir = new File(Environment.getExternalStorageDirectory(), service.storeDir);
} else {
downloadDir = new File(service.getExternalCacheDir(), "update");
}
} else {
downloadDir = new File(service.getCacheDir(), "update");
}
if (!downloadDir.exists()) {
downloadDir.mkdirs();
}
return downloadDir;
}
@Override
public void onCreate() {
super.onCreate();
appName = getApplicationName();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (!startDownload && intent != null) {
startDownload = true;
downloadUrl = intent.getStringExtra(URL);
icoResId = intent.getIntExtra(ICO_RES_ID, DEFAULT_RES_ID);
icoSmallResId = intent.getIntExtra(ICO_SMALL_RES_ID, DEFAULT_RES_ID);
storeDir = intent.getStringExtra(STORE_DIR);
updateProgress = intent.getIntExtra(UPDATE_PROGRESS, UPDATE_NUMBER_SIZE);
downloadNotificationFlag = intent.getIntExtra(DOWNLOAD_NOTIFICATION_FLAG, 0);
downloadErrorNotificationFlag = intent.getIntExtra(DOWNLOAD_ERROR_NOTIFICATION_FLAG, 0);
downloadSuccessNotificationFlag = intent.getIntExtra(DOWNLOAD_SUCCESS_NOTIFICATION_FLAG, 0);
isSendBroadcast = intent.getBooleanExtra(IS_SEND_BROADCAST, false);
if (DEBUG) {
Log.d(TAG, "downloadUrl: " + downloadUrl);
Log.d(TAG, "icoResId: " + icoResId);
Log.d(TAG, "icoSmallResId: " + icoSmallResId);
Log.d(TAG, "storeDir: " + storeDir);
Log.d(TAG, "updateProgress: " + updateProgress);
Log.d(TAG, "downloadNotificationFlag: " + downloadNotificationFlag);
Log.d(TAG, "downloadErrorNotificationFlag: " + downloadErrorNotificationFlag);
Log.d(TAG, "downloadSuccessNotificationFlag: " + downloadSuccessNotificationFlag);
Log.d(TAG, "isSendBroadcast: " + isSendBroadcast);
}
notifyId = startId;
buildNotification();
buildBroadcast();
downloadApkTask = new DownloadApk(this);
downloadApkTask.execute(downloadUrl);
}
return super.onStartCommand(intent, flags, startId);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return localBinder;
}
@Override
public boolean onUnbind(Intent intent) {
return true;
}
public void setUpdateProgressListener(UpdateProgressListener updateProgressListener) {
this.updateProgressListener = updateProgressListener;
}
@Override
public void onDestroy() {
if (downloadApkTask != null) {
downloadApkTask.cancel(true);
}
if (updateProgressListener != null) {
updateProgressListener = null;
}
localIntent = null;
builder = null;
super.onDestroy();
}
public String getApplicationName() {
PackageManager packageManager = null;
ApplicationInfo applicationInfo = null;
try {
packageManager = getApplicationContext().getPackageManager();
applicationInfo = packageManager.getApplicationInfo(getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
applicationInfo = null;
}
String applicationName =
(String) packageManager.getApplicationLabel(applicationInfo);
return applicationName;
}
private void buildBroadcast() {
if (!isSendBroadcast) {
return;
}
localBroadcastManager = LocalBroadcastManager.getInstance(this);
localIntent = new Intent(ACTION);
}
private void sendLocalBroadcast(int status, int progress) {
if (!isSendBroadcast || localIntent == null) {
return;
}
localIntent.putExtra(STATUS, status);
localIntent.putExtra(PROGRESS, progress);
localBroadcastManager.sendBroadcast(localIntent);
}
private void buildNotification() {
manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
builder = new NotificationCompat.Builder(this);
builder.setContentTitle(getString(R.string.update_app_model_prepare, appName))
.setWhen(System.currentTimeMillis())
.setProgress(100, 1, false)
.setSmallIcon(icoSmallResId)
.setLargeIcon(BitmapFactory.decodeResource(
getResources(), icoResId))
.setDefaults(downloadNotificationFlag);
manager.notify(notifyId, builder.build());
}
private void start() {
builder.setContentTitle(appName);
builder.setContentText(getString(R.string.update_app_model_progress, 1, "%"));
//setChannelId 必须添加否则不能在通知栏显示(Android 8.0)
builder.setChannelId(getPackageName());
manager.notify(notifyId, builder.build());
sendLocalBroadcast(UPDATE_PROGRESS_STATUS, 1);
if (updateProgressListener != null) {
updateProgressListener.start();
}
}
/**
* @param progress download percent , max 100
*/
private void update(int progress) {
if (progress - lastProgressNumber > updateProgress) {
lastProgressNumber = progress;
builder.setProgress(100, progress, false);
builder.setContentText(getString(R.string.update_app_model_progress, progress, "%"));
manager.notify(notifyId, builder.build());
sendLocalBroadcast(UPDATE_PROGRESS_STATUS, progress);
if (updateProgressListener != null) {
updateProgressListener.update(progress);
}
}
}
private void success(String path) {
builder.setProgress(0, 0, false);
builder.setContentText(getString(R.string.update_app_model_success));
Intent i = installIntent(this, path);
PendingIntent intent = PendingIntent.getActivity(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(intent);
builder.setDefaults(downloadSuccessNotificationFlag);
Notification n = builder.build();
n.contentIntent = intent;
manager.notify(notifyId, n);
sendLocalBroadcast(UPDATE_SUCCESS_STATUS, 100);
if (updateProgressListener != null) {
updateProgressListener.success();
}
startActivity(i);
stopSelf();
}
private void error() {
Intent i = webLauncher(downloadUrl);
PendingIntent intent = PendingIntent.getActivity(this, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentText(getString(R.string.update_app_model_error));
builder.setContentIntent(intent);
builder.setProgress(0, 0, false);
builder.setDefaults(downloadErrorNotificationFlag);
Notification n = builder.build();
n.contentIntent = intent;
manager.notify(notifyId, n);
sendLocalBroadcast(UPDATE_ERROR_STATUS, -1);
if (updateProgressListener != null) {
updateProgressListener.error();
}
stopSelf();
}
private static class DownloadApk extends AsyncTask<String, Integer, String> {
private WeakReference<UpdateService> updateServiceWeakReference;
public DownloadApk(UpdateService service) {
updateServiceWeakReference = new WeakReference<>(service);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
UpdateService service = updateServiceWeakReference.get();
if (service != null) {
service.start();
}
}
@Override
protected String doInBackground(String... params) {
final String downloadUrl = params[0];
final File file = new File(UpdateService.getDownloadDir(updateServiceWeakReference.get()),
UpdateService.getSaveFileName(downloadUrl));
if (DEBUG) {
Log.d(TAG, "download url is " + downloadUrl);
Log.d(TAG, "download apk cache at " + file.getAbsolutePath());
}
File dir = file.getParentFile();
if (!dir.exists()) {
dir.mkdirs();
}
HttpURLConnection httpConnection = null;
InputStream is = null;
FileOutputStream fos = null;
int updateTotalSize = 0;
URL url;
try {
url = new URL(downloadUrl);
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setConnectTimeout(20000);
httpConnection.setReadTimeout(20000);
if (DEBUG) {
Log.d(TAG, "download status code: " + httpConnection.getResponseCode());
}
if (httpConnection.getResponseCode() != 200) {
return null;
}
updateTotalSize = httpConnection.getContentLength();
if (file.exists()) {
if (updateTotalSize == file.length()) {
// 下载完成
return file.getAbsolutePath();
} else {
file.delete();
}
}
file.createNewFile();
is = httpConnection.getInputStream();
fos = new FileOutputStream(file, false);
byte buffer[] = new byte[4096];
int readSize = 0;
int currentSize = 0;
while ((readSize = is.read(buffer)) > 0) {
fos.write(buffer, 0, readSize);
currentSize += readSize;
publishProgress((currentSize * 100 / updateTotalSize));
}
// download success
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (httpConnection != null) {
httpConnection.disconnect();
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return file.getAbsolutePath();
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (DEBUG) {
Log.d(TAG, "current progress is " + values[0]);
}
UpdateService service = updateServiceWeakReference.get();
if (service != null) {
service.update(values[0]);
}
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
UpdateService service = updateServiceWeakReference.get();
if (service != null) {
if (s != null) {
service.success(s);
} else {
service.error();
}
}
}
}
/**
* a builder class helper use UpdateService
*/
public static class Builder {
private String downloadUrl;
private int icoResId = DEFAULT_RES_ID; //default app ico
private int icoSmallResId = DEFAULT_RES_ID;
private int updateProgress = UPDATE_NUMBER_SIZE; //update notification progress when it add number
private String storeDir; //default sdcard/Android/package/update
private int downloadNotificationFlag;
private int downloadSuccessNotificationFlag;
private int downloadErrorNotificationFlag;
private boolean isSendBroadcast;
protected Builder(String downloadUrl) {
this.downloadUrl = downloadUrl;
}
public static Builder create(String downloadUrl) {
if (downloadUrl == null) {
throw new NullPointerException("downloadUrl == null");
}
return new Builder(downloadUrl);
}
public String getDownloadUrl() {
return downloadUrl;
}
public int getIcoResId() {
return icoResId;
}
public Builder setIcoResId(int icoResId) {
this.icoResId = icoResId;
return this;
}
public int getIcoSmallResId() {
return icoSmallResId;
}
public Builder setIcoSmallResId(int icoSmallResId) {
this.icoSmallResId = icoSmallResId;
return this;
}
public int getUpdateProgress() {
return updateProgress;
}
public Builder setUpdateProgress(int updateProgress) {
if (updateProgress < 1) {
throw new IllegalArgumentException("updateProgress < 1");
}
this.updateProgress = updateProgress;
return this;
}
public String getStoreDir() {
return storeDir;
}
public Builder setStoreDir(String storeDir) {
this.storeDir = storeDir;
return this;
}
public int getDownloadNotificationFlag() {
return downloadNotificationFlag;
}
public Builder setDownloadNotificationFlag(int downloadNotificationFlag) {
this.downloadNotificationFlag = downloadNotificationFlag;
return this;
}
public int getDownloadSuccessNotificationFlag() {
return downloadSuccessNotificationFlag;
}
public Builder setDownloadSuccessNotificationFlag(int downloadSuccessNotificationFlag) {
this.downloadSuccessNotificationFlag = downloadSuccessNotificationFlag;
return this;
}
public int getDownloadErrorNotificationFlag() {
return downloadErrorNotificationFlag;
}
public Builder setDownloadErrorNotificationFlag(int downloadErrorNotificationFlag) {
this.downloadErrorNotificationFlag = downloadErrorNotificationFlag;
return this;
}
public boolean isSendBroadcast() {
return isSendBroadcast;
}
public Builder setIsSendBroadcast(boolean isSendBroadcast) {
this.isSendBroadcast = isSendBroadcast;
return this;
}
public Builder build(Context context) {
if (context == null) {
throw new NullPointerException("context == null");
}
Intent intent = new Intent();
intent.setClass(context, UpdateService.class);
intent.putExtra(URL, downloadUrl);
if (icoResId == DEFAULT_RES_ID) {
icoResId = getIcon(context);
}
if (icoSmallResId == DEFAULT_RES_ID) {
icoSmallResId = icoResId;
}
intent.putExtra(ICO_RES_ID, icoResId);
intent.putExtra(STORE_DIR, storeDir);
intent.putExtra(ICO_SMALL_RES_ID, icoSmallResId);
intent.putExtra(UPDATE_PROGRESS, updateProgress);
intent.putExtra(DOWNLOAD_NOTIFICATION_FLAG, downloadNotificationFlag);
intent.putExtra(DOWNLOAD_SUCCESS_NOTIFICATION_FLAG, downloadSuccessNotificationFlag);
intent.putExtra(DOWNLOAD_ERROR_NOTIFICATION_FLAG, downloadErrorNotificationFlag);
intent.putExtra(IS_SEND_BROADCAST, isSendBroadcast);
context.startService(intent);
return this;
}
private int getIcon(Context context) {
final PackageManager packageManager = context.getPackageManager();
ApplicationInfo appInfo = null;
try {
appInfo = packageManager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (appInfo != null) {
return appInfo.icon;
}
return 0;
}
}
}
/**
* 下载回调
*/
public interface UpdateProgressListener {
/**
* download start
*/
void start();
/**
* update download progress
* @param progress
*/
void update(int progress);
/**
* download success
*/
void success();
/**
* download error
*/
void error();
}
UpdateService.Builder.create("服务器给的下载路径")
.setStoreDir("下载路径")//default sdcard/Android/package/update
.setIsSendBroadcast(true)
.setIcoResId(android.R.drawable.ic_notification_clear_all)
.setIcoSmallResId(android.R.drawable.ic_notification_overlay)
.build(context);
三方框架源码地址
Android getActiveNotifications抛出SecurityException
我在NotificationService中使用AsyncTask来获取通知.代码如下.
private class AsyncProcessNotification extends AsyncTask<Void,Void,Void> { @Override protected Void doInBackground(Void... params) { int notificationType = MainApplication.settingNotificationType; MainApplication.clearNotificationItems(); if (MainApplication.settingNotificationType == Constants.KEY_NOTIFICATION_TYPE_disABLED) { Log.i(TAG,"Notifications disabled"); return null; } if (PermissionHelper.isNotificationPermissionGranted(getApplicationContext())) { if (getActiveNotifications() == null || getActiveNotifications().length == 0) { Log.i(TAG,"No notifications found"); return null; } Log.i(TAG,"Getting " + getActiveNotifications().length +" notifications"); Log.i(TAG,"Notification type " + notificationType); for (StatusBarNotification statusBarNotification : getActiveNotifications()) { // Process notifications } } else { // } return null; } @Override protected void onPostExecute(Void result) { Intent notify = new Intent(Constants.ACTION_NOTIFICATION_LISTENER); sendbroadcast(notify); } }
奇怪的是根据
Crashlytics,有时它在if(getActiveNotifications()== null || getActiveNotifications().length == 0)失败,有时它在Log.i失败(TAG,“获取”getActiveNotifications().length“notifications”);
要检查权限,我使用以下方法.
public static boolean isNotificationPermissionGranted(Context context) { Set<String> appList = notificationmanagerCompat.getEnabledListenerPackages(context); for (String l:appList) { if (l.equals(context.getPackageName())) { return true; } } return false; }
堆栈跟踪:
Fatal Exception: java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$3.done(AsyncTask.java:309) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) at java.util.concurrent.FutureTask.setException(FutureTask.java:223) at java.util.concurrent.FutureTask.run(FutureTask.java:242) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818) Caused by java.lang.SecurityException: disallowed call from unkNown notification listener: android.service.notification.INotificationListener$Stub$Proxy@3e9880d at android.os.Parcel.readException(Parcel.java:1599) at android.os.Parcel.readException(Parcel.java:1552) at android.app.Inotificationmanager$Stub$Proxy.getActiveNotificationsFromListener(Inotificationmanager.java:1046) at android.service.notification.NotificationListenerService.getActiveNotifications(NotificationListenerService.java:467) at android.service.notification.NotificationListenerService.getActiveNotifications(NotificationListenerService.java:420) at com.afd.app.lockscreen.ios11.lib.service.NotificationService$AsyncProcessNotification.doInBackground(NotificationService.java:120) at com.afd.app.lockscreen.ios11.lib.service.NotificationService$AsyncProcessNotification.doInBackground(NotificationService.java:97) at android.os.AsyncTask$2.call(AsyncTask.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)
我知道我必须做一些愚蠢但却无法弄清楚是什么.有人可以帮忙吗?谢谢!
解决方法
I hit the same error in my notification listener service. I was able
to solve it by waiting for the listener service to get connected to the
notification manager before calling any of the
NotificationListenerService methods.
@Override public void onListenerConnected() { Log.i(TAG,"Listener connected"); listenerConnected = true; } private class AsyncProcessNotification extends AsyncTask<Void,Void> { protected Void doInBackground(Void... params) { ... // wait until our notification listener service is connected // to the notification manager Log.i(TAG,"Waiting for listener to be connected..."); while(!listenerConnected); // Call getActiveNotifications after this for (StatusBarNotification sbn : getActiveNotifications()) { processNotifications(sbn); } } // rest of the AsyncTask here }
Android lollipop java.lang.SecurityException:用户和当前进程都没有android.permission.BLUETOOTH_PRIVILEGED
表现:
<uses-permission android:name="android.permission.BLUetoOTH" /> <uses-permission android:name="android.permission.BLUetoOTH_ADMIN" /> <uses-permission android:name="android.permission.BLUetoOTH_PRIVILEGED" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />
码:
mBleScanner.startScan(filters,scanSettings,mLeScanCallback); private ScanCallback mLeScanCallback = new ScanCallback() { @Override public void onScanResult(int callbackType,ScanResult result) { BluetoothDevice device = result.getDevice(); if(device.getName() != null) { if(device.getName().toupperCase().contains("MyDevice")) { mBleScanner.stopScan(mLeScanCallback); if (device.getBondState() == BluetoothDevice.BOND_BONDED) { Connect(device.getAddress().toString()); } else { // pair device device.setPairingConfirmation(true); device.createBond(); } } } } }; ... .. . private void BondDevice(BluetoothGattCharacteristic bgc,boolean pnEnable) { boolean bool = gatt.setCharacteristicNotification(bgc,true); // this line throw security exception BluetoothGattDescriptor bgd=bgc.getDescriptor(UUID.fromString(BLE_DESCRIPTOR_NOTIFY)); byte[] arrayOfByte = pnEnable ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE: BluetoothGattDescriptor.disABLE_NOTIFICATION_VALUE; gattDescriptor.setValue(arrayOfByte); mBluetoothGatt.writeDescriptor(bgd); }
堆栈跟踪:
04-27 12:36:24.559: W/BluetoothGatt(17764): Unhandled exception in callback 04-27 12:36:24.559: W/BluetoothGatt(17764): java.lang.SecurityException: Need BLUetoOTH_PRIVILEGED permission: Neither user 10215 nor current process has android.permission.BLUetoOTH_PRIVILEGED. 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.os.Parcel.readException(Parcel.java:1540) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.os.Parcel.readException(Parcel.java:1493) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.bluetooth.IBluetoothGatt$Stub$Proxy.registerForNotification(IBluetoothGatt.java:1163) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.bluetooth.BluetoothGatt.setCharacteristicNotification(BluetoothGatt.java:1239) 04-27 12:36:24.559: W/BluetoothGatt(17764): at com.vibease.ap3.service.ServiceBLE.BondDevice(ServiceBLE.java:568) 04-27 12:36:24.559: W/BluetoothGatt(17764): at com.vibease.ap3.service.ServiceBLE.CheckDevice(ServiceBLE.java:518) 04-27 12:36:24.559: W/BluetoothGatt(17764): at com.vibease.ap3.service.ServiceBLE.access$7(ServiceBLE.java:493) 04-27 12:36:24.559: W/BluetoothGatt(17764): at com.vibease.ap3.service.ServiceBLE$2.onServicesdiscovered(ServiceBLE.java:373) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.bluetooth.BluetoothGatt$1.onSearchComplete(BluetoothGatt.java:309) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:217) 04-27 12:36:24.559: W/BluetoothGatt(17764): at android.os.Binder.execTransact(Binder.java:446)
解决方法
04-27 12:36:24.559: W/BluetoothGatt(17764): java.lang.SecurityException: Need
BLUetoOTH_PRIVILEGED@H_301_21@ permission: Neither user 10215 nor current process has
android.permission.BLUetoOTH_PRIVILEGED@H_301_21@.
只需添加它要求的权限:
<uses-permission android:name="android.permission.BLUetoOTH_PRIVILEGED" />
Android M 6.0 – SecurityException试图删除帐户
我可以使用清单中的以下权限在Pre Marshmallow设备上成功添加和删除帐户:
<uses-permission android:name="android.permission.GET_ACCOUNTS"/> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/> <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
使用sdk 22进行编译并使用sdk 22进行编译时,应自动授予这些权限.以下代码:
accountManager.removeAccount(getAccount(),activity,new AccountManagerCallback<Bundle>() { @Override public void run(AccountManagerFuture<Bundle> accountManagerFuture) { try { Bundle bundle = accountManagerFuture.getResult(); boolean success = bundle.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); if (success) { Toast.makeText(activity,activity.getString(R.string.successfully_loggedout),Toast.LENGTH_LONG).show(); afterlogoutSuccess(activity); } else { Toast.makeText(activity.getApplicationContext(),activity.getString(R.string.Failed_to_logout),Toast.LENGTH_LONG).show(); } onlogoutListener.onlogoutFinished(success); return; } catch (OperationCanceledException e) { Log.e(TAG,"Operation cancelled exception:",e); } catch (IOException e) { Log.e(TAG,"IOException:",e); } catch (AuthenticatorException e) { Log.e(TAG,"AuthenticatorException:",e); } onlogoutListener.onlogoutFinished(false); } },null);
失败,出现以下异常:
java.lang.SecurityException: uid 10057 cannot remove accounts of type: com.mycompany.accounts at android.os.Parcel.readException(Parcel.java:1599) at android.os.Parcel.readException(Parcel.java:1552) at android.accounts.IAccountManager$Stub$Proxy.removeAccount(IAccountManager.java:897) at android.accounts.AccountManager$7.doWork(AccountManager.java:900) at android.accounts.AccountManager$AmsTask.start(AccountManager.java:1888) at android.accounts.AccountManager.removeAccount(AccountManager.java:897) at com.mycomp.actualapp.utils.LoginHelper$4.doInBackground(LoginHelper.java:282) at com.mycomp.actualapputils.LoginHelper$4.doInBackground(LoginHelper.java:242) at android.os.AsyncTask$2.call(AsyncTask.java:295) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)
奇怪的是,这个代码在Pre Marshmallow设备上运行正常,没有任何问题.
在旁注中,我注意到使用sdk 22进行编译并且定位22:转到“设置>应用>我的应用(com.mycomp.actualapp)>权限”我只看到两个权限,“电话”“存储” .
我注意到用sdk 23编译并且目标23:我看到三个权限,“电话”,“存储”和“联系人”.
我尝试过以下方法:
>切换到使用sdk 23编译 – 在应用程序设置中授予所有权限,再次尝试删除帐户.仍然失败,同样的例外.
>使用22进行编译并将以下权限添加到清单中.确保授予所有权限.仍然失败,同样的例外:
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/> <uses-permission android:name="android.permission.READ_CONTACTS"/> <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
我可以在没有其他权限授予的情况下获取用户帐户用户名和令牌,但删除帐户不起作用.
我真的很感激任何帮助!
解决方法
就我而言,我在节点中定义了错误的包名称.
只需修复它就能完美运行.
<帐户认证符>
的xmlns:机器人= “http://schemas.android.com/apk/res/android”
android:accountType =“你的正确数据包名称”“.accounts”
机器人:图标= “@绘制/ ic_launcher”
机器人:标签= “XXX”
机器人:smallIcon = “@绘制/ ic_launcher”
>
< /帐户认证符>
如果您的包裹名称是:com.example.android然后帐户类型应该是:com.example.android.accounts
今天关于android – 与FileProvider共享文件时使用grantUriPermission的SecurityException和android 共享文件夹的讲解已经结束,谢谢您的阅读,如果想了解更多关于Android 9.0 自动更新 安装包解析错误 java.lang.SecurityException: Permission Denial、Android getActiveNotifications抛出SecurityException、Android lollipop java.lang.SecurityException:用户和当前进程都没有android.permission.BLUETOOTH_PRIVILEGED、Android M 6.0 – SecurityException试图删除帐户的相关知识,请在本站搜索。
本文标签: