1. 图片选择和裁剪
Causedby:android.os.FileUriExposedException:file:///storage/emulated/0/Android/data/com.ct.client/files/com.ct.client/camere/1547090088847.jpg exposed beyond app through ClipData.Item.getUri()
第一步:
在AndroidManifest.xml清单文件中注册provider
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ct.client.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<!--元数据-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
需要注意一下几点:
exported:必须为false
grantUriPermissions:true,表示授予 URI 临时访问权限。
authorities 组件标识,都以包名开头,避免和其它应用发生冲突。
第二步:
指定共享文件的目录,需要在res文件夹中新建xml目录,并且创建file_paths
path=”“,是有特殊意义的,它代表根目录,也就是说你可以向其它的应用共享根目录及其子目录下任何一个文件了。
第三步:
使用FileProvider
根据版本号把Uri改成使用FiliProvider创建的Uri,
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
cameraFileUri=FileProvider.getUriForFile(mContext,"com.ct.client.fileProvider",newFile(saveCamerePath,saveCameraFileName));
}else{
cameraFileUri = Uri.fromFile(newFile(saveCamerePath, saveCameraFileName));
}
添加intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)来对目标应用临时授权该Uri所代表的文件
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//添加这一句表示对目标应用临时授权该Uri所代表的文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
在设置裁剪要保存的intent.putExtra(MediaStore.EXTRA_OUTPUT, outUri);的时候,这个outUri是要使用Uri.fromFile(file)生成的,而不是使用FileProvider.getUriForFile。
2. 获取以content开头的文件拿不到正确路径
java.lang.IllegalArgumentException: column'_data'doesnotexist
拿到uri之后进行版本判断大于等于24(即Android7.0)用最新的获取路径方式
Stringstr ="";
if(Build.VERSION.SDK_INT >=24) {
str = getFilePathFromURI(this, uri);//新的方式
}
else{
str = getPath(this, uri);//你自己之前的获取方法
}
public String getFilePathFromURI(Context context, Uri contentUri) {
File rootDataDir = context.getFilesDir();
String fileName = getFileName(contentUri);
if (!TextUtils.isEmpty(fileName)) {
File copyFile = new File(rootDataDir + File.separator + fileName);
copyFile(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
public static String getFileName(Uri uri) {
if (uri == null)
return null;
String fileName = null;
String path = uri.getPath();
int cut = path.lastIndexOf('/');
if (cut != -1) {
fileName = path.substring(cut + 1);
}
return fileName;
}
public void copyFile(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
if (inputStream == null)
return;
OutputStream outputStream = new FileOutputStream(dstFile);
copyStream(inputStream, outputStream);
inputStream.close();
outputStream.close();
}catch (Exception e) {
e.printStackTrace();
}
}
public int copyStream(InputStream input, OutputStream output) throws Exception, IOException {
final int BUFFER_SIZE = 1024 * 2; byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
int count = 0, n = 0;
try {
while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n); count += n;
}
out.flush();
}finally {
try {
out.close();
} catch (IOException e) {
}
try {
in.close();
} catch (IOException e) {
}
}
return count;
}
3. 7.0的手机安装没问题,但是在8.0上安装,app没有反应,一闪而过
增加新权限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
把
Intent intent =newIntent(Intent.ACTION_VIEW)
改为
Intent intent =newIntent(Intent.ACTION_INSTALL_PACKAGE);
4. 通知栏不显示
在Application中创建渠道
@Override
protectedvoidonCreate(){
super.onCreate();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelId ="chat";
String channelName ="聊天消息";
intimportance = NotificationManager.IMPORTANCE_HIGH;
createNotificationChannel(channelId, channelName, importance);
channelId ="subscribe";
channelName ="订阅消息";
importance = NotificationManager.IMPORTANCE_DEFAULT;
createNotificationChannel(channelId, channelName, importance);
}
}
@TargetApi(Build.VERSION_CODES.O)
privatevoidcreateNotificationChannel(String channelId, String channelName,intimportance){
NotificationChannel channel =newNotificationChannel(channelId, channelName, importance);
NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel);
}
根据渠道发送消息new NotificationCompat.Builder(this, channelName)
public class MainActivity extends AppCompatActivity{
...
publicvoidsendChatMsg(View view){
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification =newNotificationCompat.Builder(this,"chat")
.setContentTitle("收到一条聊天消息")
.setContentText("今天中午吃什么?")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon))
.setAutoCancel(true)
.build();
manager.notify(1, notification);
}
publicvoidsendSubscribeMsg(View view){
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification =newNotificationCompat.Builder(this,"subscribe")
.setContentTitle("收到一条订阅消息")
.setContentText("地铁沿线30万商铺抢购中!")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.icon)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon))
.setAutoCancel(true)
.build();
manager.notify(2, notification);
}
}