안 드 로 이 드 10 구덩이 매 립 적합 가이드(실제 경험 코드)
Android 10 구덩이 매 립 매 립 매 칭 안내,실제 경험 코드 포함,번역 문 서 를 그대로 옮 기지 않 습 니 다.
1.Region.Op 관련 이상:java.lang.IllegalArgument 예외:유효 하지 않 은 Region.Op-INTERSECT 및 DIFFERENCE 만 허 용 됩 니 다.
...해 야 한다 targetSdkVersion >= Build.VERSION_CODES.P 시 canvas.clipPath(path,Region.Op.XXX)를 호출 합 니 다.발생 하 는 이상 은 다음 과 같 습 니 다.
@Deprecated
public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
checkValidClipOp(op);
return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
}
private static void checkValidClipOp(@NonNull Region.Op op) {
if (sCompatiblityVersion >= Build.VERSION_CODES.P
&& op != Region.Op.INTERSECT && op != Region.Op.DIFFERENCE) {
throw new IllegalArgumentException(
"Invalid Region.Op - only INTERSECT and DIFFERENCE are allowed");
}
}
대상 버 전이 Android P 에서 시작 할 때 Canvas.clipPath(@NonNull Path path,@NonNull Region.Op op)를 볼 수 있 습 니 다.이미 폐기 되 었 고 이상 위험 을 포함 한 폐기 API 만 있 습 니 다. Region.Op.INTERSECT 와 Region.Op.DIFERENCE 가 호 환 되 고 거의 모든 블 로그 솔 루 션 은 다음 과 같이 간단 하고 난폭 합 니 다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
canvas.clipPath(path);
} else {
canvas.clipPath(path, Region.Op.XOR);// REPLACE、UNION
}
그러나 우 리 는 반드시 고급 논리 연산 효과 가 필요 하 다.어떻게 해 야 합 니까?예 를 들 어 소설의 모방 페이지 읽 기 효과 에 대해 해결 방안 은 다음 과 같다.Path.op 으로 대체 하고 Path 를 먼저 연산 한 다음 에
canvas.clipPath:
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P){
Path mPathXOR = new Path();
mPathXOR.moveTo(0,0);
mPathXOR.lineTo(getWidth(),0);
mPathXOR.lineTo(getWidth(),getHeight());
mPathXOR.lineTo(0,getHeight());
mPathXOR.close();
// Canvas View , Path
mPathXOR.op(mPath0, Path.Op.XOR);
canvas.clipPath(mPathXOR);
}else {
canvas.clipPath(mPath0, Region.Op.XOR);
}
2.명문 HTTP 제한...해 야 한다 targetSdkVersion >= Build.VERSION_CODES.P 에 서 는 기본적으로 HTTP 요청 을 제한 하고 로그 가 나타 납 니 다.
java.net.UnknownServiceException: CLEARTEXT communication to xxx not permitted by network security policy
첫 번 째 해결 방안:AndroidManifest.xml 에 응용 프로그램 에 다음 과 같은 노드 코드 를 추가 합 니 다.
<application android:usesCleartextTraffic="true">
두 번 째 솔 루 션:res 디 렉 터 리 에 xml 디 렉 터 리 를 새로 만 들 고 xml 디 렉 터 리 에 xml 파일 network 를 새로 만 듭 니 다.security_config.xml,그리고 AndroidManifest.xml 에 Application 에 다음 노드 코드 를 추가 합 니 다.
android:networkSecurityConfig="@xml/network_config"
이름 은 랜 덤 입 니 다.내용 은 다음 과 같 습 니 다.
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
3.Android Q 의 미디어 자원 읽 기 및 쓰기1.스 캔 시스템 앨범,동 영상 등,이미지,동 영상 선택 기 는 모두 ContentResolver 를 통 해 제 공 됩 니 다.주요 코드 는 다음 과 같 습 니 다.
private static final String[] IMAGE_PROJECTION = {
MediaStore.Images.Media.DATA,
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME};
Cursor imageCursor = mContext.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
IMAGE_PROJECTION, null, null, IMAGE_PROJECTION[0] + " DESC");
String path = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[0]));
String name = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[1]));
int id = imageCursor.getInt(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[2]));
String folderPath = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[3]));
String folderName = imageCursor.getString(imageCursor.getColumnIndexOrThrow(IMAGE_PROJECTION[4]));
//Android Q Content Uri + id , File , Video, MediaStore.Videos
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
path = MediaStore.Images.Media
.EXTERNAL_CONTENT_URI
.buildUpon()
.appendPath(String.valueOf(id)).build().toString();
}
2.공유 디 렉 터 리 파일 의 존재 여 부 를 판단 합 니 다.Android Q 부터 공유 디 렉 터 리 File API 가 모두 효력 을 상실 하고 new File(path).exists()를 직접 통과 할 수 없습니다.공유 디 렉 터 리 파일 이 존재 하 는 지 여 부 를 판단 합 니 다.정확 한 방법 은 다음 과 같 습 니 다.
public static boolean isAndroidQFileExists(Context context, String path){
AssetFileDescriptor afd = null;
ContentResolver cr = context.getContentResolver();
try {
Uri uri = Uri.parse(path);
afd = cr.openAssetFileDescriptor(uri, "r");
if (afd == null) {
return false;
} else {
close(afd);
}
} catch (FileNotFoundException e) {
return false;
}finally {
close(afd);
}
return true;
}
3.copy 또는 공유 디 렉 터 리 에 파일 을 다운로드 하고 Bitmap 를 저장 합 니 다.예 를 들 어 Download,MIMETYPE 형식 은 자체 적 으로 대응 하 는 파일 형식 을 참고 할 수 있 습 니 다.여 기 는 APK 에 대해 서 만 설명 할 수 있 습 니 다.개인 디 렉 터 리 copy 에서 공유 디 렉 터 리 demo 까지 다음 과 같 습 니 다.
public static void copyToDownloadAndroidQ(Context context, String sourcePath, String fileName, String saveDirName){
ContentValues values = new ContentValues();
values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
values.put(MediaStore.Downloads.MIME_TYPE, "application/vnd.android.package-archive");
values.put(MediaStore.Downloads.RELATIVE_PATH, "Download/" + saveDirName.replaceAll("/","") + "/");
Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
ContentResolver resolver = context.getContentResolver();
Uri insertUri = resolver.insert(external, values);
if(insertUri == null) {
return;
}
String mFilePath = insertUri.toString();
InputStream is = null;
OutputStream os = null;
try {
os = resolver.openOutputStream(insertUri);
if(os == null){
return;
}
int read;
File sourceFile = new File(sourcePath);
if (sourceFile.exists()) { //
is = new FileInputStream(sourceFile); //
byte[] buffer = new byte[1444];
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
close(is,os);
}
}
4.이미지 저장 관련
/**
* MediaStore , AndroidQ, ,
*
* @param context context
* @param sourceFile
* @param saveFileName
* @param saveDirName picture
* @return
*/
public static boolean saveImageWithAndroidQ(Context context,
File sourceFile,
String saveFileName,
String saveDirName) {
String extension = BitmapUtil.getExtension(sourceFile.getAbsolutePath());
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DESCRIPTION, "This is an image");
values.put(MediaStore.Images.Media.DISPLAY_NAME, saveFileName);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/png");
values.put(MediaStore.Images.Media.TITLE, "Image.png");
values.put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/" + saveDirName);
Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
ContentResolver resolver = context.getContentResolver();
Uri insertUri = resolver.insert(external, values);
BufferedInputStream inputStream = null;
OutputStream os = null;
boolean result = false;
try {
inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
if (insertUri != null) {
os = resolver.openOutputStream(insertUri);
}
if (os != null) {
byte[] buffer = new byte[1024 * 4];
int len;
while ((len = inputStream.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
}
result = true;
} catch (IOException e) {
result = false;
} finally {
close(os, inputStream);
}
return result;
}
4.EditText 는 기본적으로 초점 을 가 져 오지 않 고 키보드 가 자동 으로 꺼 지지 않 습 니 다.질문 targetSdkVersion >= Build.VERSION_CODES.P 의 경우 장치 버 전 은 Android P 이상 버 전 입 니 다.해결 방법 은 onCreate 에 다음 코드 를 추가 하면 초점 을 얻 을 수 있 습 니 다.키보드 팝 업 이 필요 하면 지연 시 킬 수 있 습 니 다.
mEditText.post(() -> {
mEditText.requestFocus();
mEditText.setFocusable(true);
mEditText.setFocusableInTouchMode(true);
});
5.APK Intent 및 기타 공유 파일 관련 Intent 설치
/*
* Android N , FileProvider , Android Q File API , Uri ,
* , , Intent.FLAG_GRANT_READ_URI_PERMISSION
*/
private void installApk() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
// Android Q, mFilePath ContentResolver ,
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(mFilePath) ,"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
return ;
}
File file = new File(saveFileName + "demo.apk");
if (!file.exists())
return;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), "net.oschina.app.provider", file);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
}
6.Activity 투명 관련,windowIsTranslucent 속성Android Q 에 또 하나의 구멍 이 있 습 니 다.반투명 Activity 를 표시 하려 면 안 드 로 이 드 10 이전에 일반 스타일 Activity 는 window IsTranslucent=true 만 설정 하면 됩 니 다.하지만 AndroidQ 에 도착 하면 효과 가 없습니다.또한 동적 으로 View 를 설정 하면 화면 에 잔상 이 나타 납 니 다.
해결 방법:Dialog 스타일 Activity 를 사용 하고 window IsFloating=true 를 설정 합 니 다.이때 문제 가 다시 발생 했 습 니 다.Activity 루트 레이아웃 에 fitsSystem Window=true 가 설정 되 어 있 지 않 으 면 기본적으로 상태 표시 줄 에 침입 하지 않 아 화면 이 정상 으로 보 입 니 다.
7.클립보드 호 환
Android Q 에 서 는 대화 가능 한 상황(기본 입력 법 자체 가 상호작용 가능)에 만 클립보드 와 감청 클립보드 의 변 화 를 방문 할 수 있 습 니 다.onResume 리 셋 에서 도 클립보드 에 직접 접근 할 수 없습니다.이렇게 하면 배경 에서 미 친 감청 응답 클립보드 의 내용,미 친 팝 업 창 을 피 할 수 있 습 니 다.
따라서 클립보드 감청 이 더 필요 하 다 면 생애 주기 리 셋 을 적용 해 앱 백 엔 드 를 되 돌려 줌 으로 써 클립보드 방문 을 몇 밀리초 늦 추고 마지막 으로 방문 해 얻 은 클립보드 내용 을 저장 해 매번 변화 가 있 는 지 를 비교 해 다음 작업 을 할 수 있다.
8.제3자 가 사진 을 공유 하 는 등 작업 을 하고 파일 경 로 를 직접 사용 하 는 경우,예 를 들 어 QQ 이미지 공유 등 은 모두 주의해 야 합 니 다.이것 은 불가능 합 니 다.모두 MediaStore 등 API 를 통 해 Uri 를 가 져 와 서 만 작업 할 수 있 습 니 다.
이것 은 우리 가 sdk 에서 29 로 업그레이드 할 때 발생 하 는 실제 문제 에 따라 나열 한 것 입 니 다.번역 AndroidQ 의 행위 변경 이 아니 라 구체 적 인 문 제 는 자신의 실제 에 따라 스스로 해결 하 십시오.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Android 10도 클립보드를 쓰고 싶어요.화면을 시작할 때 클립보드를 검색하려면 onResume 등에서 ClipboardManager를 호출해서 검색합니다. MainActivity.kt 하지만 안드로이드 10에서 위와 같은 방법으로 클립보드의 내용을 얻으려...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.