【发布时间】:2021-02-17 06:19:07
【问题描述】:
我想将 android 视图转换为图像文件并将其保存到 Android Oreo 设备的内部存储中。但我的以下代码不起作用。
这是 XML 代码:-
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@color/teal_200"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/btnSaveID"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/kohli" />
</LinearLayout>
<Button
android:id="@+id/btnSaveID"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:paddingLeft="50dp"
android:paddingRight="50dp"
android:text="@string/save"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/layout1" />
</androidx.constraintlayout.widget.ConstraintLayout>
这里是JAVA代码:-
public class MainActivity extends AppCompatActivity {
LinearLayout layout;
OutputStream outputStream;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = findViewById(R.id.layout1);
findViewById(R.id.btnSaveID).setOnClickListener(v -> {
if (Build.VERSION.SDK_INT >= 23) {
String requiredPermission = Manifest.permission.READ_EXTERNAL_STORAGE;
int checkVal = checkCallingOrSelfPermission(requiredPermission);
if (checkVal == PackageManager.PERMISSION_GRANTED) {
saveImage2(layout, MainActivity.this);
} else {
checkPermission(layout);
}
} else {
saveImage2(layout, MainActivity.this);
}
});
}
private void saveImage2(LinearLayout layout1, Context context) {
layout1.setDrawingCacheEnabled(true);
layout1.buildDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(layout1.getWidth(), layout1.getHeight(), Bitmap.Config.ARGB_8888);
if (bitmap != null) {
Canvas canvas = new Canvas(bitmap);
layout1.draw(canvas);
Drawable bgDrawable = layout1.getBackground();
if (bgDrawable != null) {
bgDrawable.draw(canvas);
} else {
canvas.drawColor(Color.WHITE);
}
layout1.draw(canvas);
String name = System.currentTimeMillis() + ".png";
try {
savePng(context, bitmap, name);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void savePng(Context context, Bitmap bitmap, @NonNull String name) throws IOException {
Uri uri;
OutputStream fileOutputStream;
String path;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
ContentResolver resolver = context.getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, name + ".png");
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/png");
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
fileOutputStream = resolver.openOutputStream(Objects.requireNonNull(uri));
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
Toast.makeText(context, "Saved!", Toast.LENGTH_SHORT).show();
} else {
String imagePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File image = new File(imagePath, name + ".png");
fileOutputStream = new FileOutputStream(image);
uri = getUriFromPath(context, imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
fileOutputStream.close();
Toast.makeText(context, "Saved!", Toast.LENGTH_SHORT).show();
path = image.getAbsolutePath();
MediaScannerConnection.scanFile(context, new String[]{path}, new String[]{"image/*"},
new MediaScannerConnection.MediaScannerConnectionClient() {
public void onMediaScannerConnected() {
}
public void onScanCompleted(String path, Uri uri) {
}
});
}
}
private static Uri getUriFromPath(Context context, String imagePath) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
return FileProvider.getUriForFile(context, "com.noobprogroammer.sampleproject.fileprovider", new File(imagePath));
return Uri.fromFile(new File(imagePath));
}
private void checkPermission(LinearLayout layout) {
PermissionListener permissionListener = new PermissionListener() {
@Override
public void onPermissionGranted() {
saveImage2(layout, MainActivity.this);
}
@Override
public void onPermissionDenied(List<String> deniedPermissions) {
Toast.makeText(MainActivity.this, "Permission required to download", Toast.LENGTH_SHORT).show();
}
};
TedPermission.with(MainActivity.this)
.setPermissionListener(permissionListener)
.setPermissions(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.check();
}
}
我也添加了路径路径:-
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>
向 Manifest 文件添加元数据:-
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.noobprogroammer.sampleproject.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
我还添加了 android:requestLegacyExternalStorage="true" 和 Internet 权限:-
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
谁能找到问题,为什么这段代码在 Android Oreo 版本上不起作用?
【问题讨论】:
-
请删除所有代码和xml等。仅发布 savePng() 函数的代码,并说明什么不起作用。
-
也不需要互联网许可和请求旧的外部存储,因此您也可以将其删除。
标签: android scope storage android-8.0-oreo