求安卓SD存储读写实例

求安卓SD存储读写实例,第1张

在Android 10及以上版本,由于Google对文件访问权限的限制,你需要使用MediaStore API来访问外部存储。这里给你一个在SD卡中读取并保存的示例。请确保在AndroidManifestxml中添加了存储权限。

在AndroidManifestxml文件中添加以下权限:

<uses-permission android:name="androidpermissionREAD_EXTERNAL_STORAGE" />

<uses-permission android:name="androidpermissionWRITE_EXTERNAL_STORAGE" />

在MainActivityjava中添加以下代码:

import androidManifest;

import androidcontentContentValues;

import androidcontentpmPackageManager;

import androidgraphicsBitmap;

import androidgraphicsBitmapFactory;

import androidnetUri;

import androidosBuild;

import androidosBundle;

import androidproviderMediaStore;

import androidutilLog;

import androidwidgetToast;

import androidxannotationNonNull;

import androidxappcompatappAppCompatActivity;

import androidxcoreappActivityCompat;

import androidxcorecontentContextCompat;

import javaioFileNotFoundException;

import javaioIOException;

import javaioInputStream;

import javaioOutputStream;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

private static final int PERMISSION_REQUEST_CODE = 100;

@Override

protected void onCreate(Bundle savedInstanceState) {

superonCreate(savedInstanceState);

setContentView(Rlayoutactivity_main);

if (ContextCompatcheckSelfPermission(this, ManifestpermissionWRITE_EXTERNAL_STORAGE) != PackageManagerPERMISSION_GRANTED) {

ActivityCompatrequestPermissions(this, new String[]{ManifestpermissionWRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);

} else {

accessExternalStorage();

}

}

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

if (requestCode == PERMISSION_REQUEST_CODE) {

if (grantResultslength > 0 && grantResults[0] == PackageManagerPERMISSION_GRANTED) {

accessExternalStorage();

} else {

ToastmakeText(this, "Permission Denied!", ToastLENGTH_SHORT)show();

}

}

}

private void accessExternalStorage() {

// Read image from external storage

Uri imageUri = MediaStoreImagesMediaEXTERNAL_CONTENT_URI;

try {

InputStream inputStream = getContentResolver()openInputStream(imageUri);

if (inputStream != null) {

Bitmap bitmap = BitmapFactorydecodeStream(inputStream);

inputStreamclose();

// Save image to external storage

ContentValues contentValues = new ContentValues();

contentValuesput(MediaStoreMediaColumnsDISPLAY_NAME, "my_saved_imagejpg");

contentValuesput(MediaStoreMediaColumnsMIME_TYPE, "image/jpeg");

contentValuesput(MediaStoreMediaColumnsRELATIVE_PATH, "DCIM/MyApp");

Uri newImageUri = getContentResolver()insert(MediaStoreImagesMediaEXTERNAL_CONTENT_URI, contentValues);

if (newImageUri != null) {

OutputStream outputStream = getContentResolver()openOutputStream(newImageUri);

if (outputStream != null) {

bitmapcompress(BitmapCompressFormatJPEG, 100, outputStream);

outputStreamclose();

ToastmakeText(this, "Image saved!", ToastLENGTH_SHORT)show();

}

}

}

} catch (FileNotFoundException e) {

Loge(TAG, "File not found", e);

} catch (IOException e) {

Loge(TAG, "I/O exception", e);

}

}

}

这个示例将会请求存储权限,然后从外部存储读取一张,并将其另存为 "my_saved_imagejpg"。 注意这个示例适用于Android 10及以上版本,对于Android 9及以下版本,你需要使用EnvironmentgetExternalStorageDirectory()来获取外部存储路径。

对于低于Android 10的版本,你可以使用EnvironmentgetExternalStorageDirectory()来访问外部存储,但是请注意,从Android 11开始,这个方法已经被弃用。

在这个示例中,我将展示如何适配不同版本的Android系统,通过检查设备的API级别来决定如何访问外部存储。

首先,在AndroidManifestxml中添加存储权限:

<uses-permission android:name="androidpermissionREAD_EXTERNAL_STORAGE" />

<uses-permission android:name="androidpermissionWRITE_EXTERNAL_STORAGE" />

然后,在MainActivityjava中添加以下代码:

import androidManifest;

import androidcontentpmPackageManager;

import androidosBuild;

import androidosBundle;

import androidosEnvironment;

import androidutilLog;

import androidwidgetToast;

import androidxannotationNonNull;

import androidxappcompatappAppCompatActivity;

import androidxcoreappActivityCompat;

import androidxcorecontentContextCompat;

import javaioFile;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

private static final int PERMISSION_REQUEST_CODE = 100;

@Override

protected void onCreate(Bundle savedInstanceState) {

superonCreate(savedInstanceState);

setContentView(Rlayoutactivity_main);

if (ContextCompatcheckSelfPermission(this, ManifestpermissionWRITE_EXTERNAL_STORAGE) != PackageManagerPERMISSION_GRANTED) {

ActivityCompatrequestPermissions(this, new String[]{ManifestpermissionWRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);

} else {

accessExternalStorage();

}

}

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

if (requestCode == PERMISSION_REQUEST_CODE) {

if (grantResultslength > 0 && grantResults[0] == PackageManagerPERMISSION_GRANTED) {

accessExternalStorage();

} else {

ToastmakeText(this, "Permission Denied!", ToastLENGTH_SHORT)show();

}

}

}

private void accessExternalStorage() {

File externalStorageDirectory;

if (BuildVERSIONSDK_INT >= BuildVERSION_CODESQ) {

externalStorageDirectory = getExternalFilesDir(EnvironmentDIRECTORY_PICTURES);

} else {

externalStorageDirectory = new File(EnvironmentgetExternalStorageDirectory(), "MyApp");

}

if (externalStorageDirectory != null) {

Logi(TAG, "External storage directory: " + externalStorageDirectorygetAbsolutePath());

File[] files = externalStorageDirectorylistFiles();

if (files != null) {

for (File file : files) {

Logi(TAG, "File: " + filegetName());

}

}

} else {

Loge(TAG, "Unable to access external storage directory");

}

}

}

在这个示例中,我们检查当前设备的API级别。如果设备运行在Android 10及以上版本,我们使用getExternalFilesDir()方法来访问外部存储;否则,我们使用已弃用的EnvironmentgetExternalStorageDirectory()方法。

这段代码将会请求存储权限,然后根据设备的Android版本来访问外部存储并遍历文件夹中的文件。

…………

回复:

在 Android 10 及以上版本中,Google 引入了分区存储,使应用程序在访问外部存储时受到限制。因此,在 Android 10

及以上版本中,我们不能像以前那样直接访问外部存储。如果您想在所有版本中使用相同的代码,可以使用兼容库(AndroidX)中的 Storage

Access Framework (SAF)。

首先,确保您在项目的 buildgradle 文件中添加了以下依赖项

implementation 'androidxdocumentfile:documentfile:101'

然后在 AndroidManifestxml 文件中添加存储权限:

<uses-permission android:name="androidpermissionREAD_EXTERNAL_STORAGE" />

<uses-permission android:name="androidpermissionWRITE_EXTERNAL_STORAGE" />

接下来,我们将使用 SAF 来获取存储目录并遍历其内容:

import androidManifest;

import androidcontentIntent;

import androidcontentpmPackageManager;

import androidnetUri;

import androidosBundle;

import androidproviderDocumentsContract;

import androidutilLog;

import androidwidgetToast;

import androidxannotationNullable;

import androidxappcompatappAppCompatActivity;

import androidxcoreappActivityCompat;

import androidxcorecontentContextCompat;

import androidxdocumentfileproviderDocumentFile;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

private static final int PERMISSION_REQUEST_CODE = 100;

private static final int OPEN_DIRECTORY_REQUEST_CODE = 200;

@Override

protected void onCreate(Bundle savedInstanceState) {

superonCreate(savedInstanceState);

setContentView(Rlayoutactivity_main);

if (ContextCompatcheckSelfPermission(this,

ManifestpermissionWRITE_EXTERNAL_STORAGE) !=

PackageManagerPERMISSION_GRANTED) {

ActivityCompatrequestPermissions(this, new

String[]{ManifestpermissionWRITE_EXTERNAL_STORAGE},

PERMISSION_REQUEST_CODE);

} else {

openDirectoryPicker();

}

}

@Override

public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

if (requestCode == PERMISSION_REQUEST_CODE) {

if (grantResultslength > 0 && grantResults[0] == PackageManagerPERMISSION_GRANTED) {

openDirectoryPicker();

} else {

ToastmakeText(this, "Permission Denied!", ToastLENGTH_SHORT)show();

}

}

}

private void openDirectoryPicker() {

Intent intent = new Intent(IntentACTION_OPEN_DOCUMENT_TREE);

startActivityForResult(intent, OPEN_DIRECTORY_REQUEST_CODE);

}

@Override

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {

superonActivityResult(requestCode, resultCode, data);

if (requestCode == OPEN_DIRECTORY_REQUEST_CODE && resultCode == RESULT_OK && data != null) {

Uri directoryUri = datagetData();

if (directoryUri != null) {

getContentResolver()takePersistableUriPermission(directoryUri,

IntentFLAG_GRANT_READ_URI_PERMISSION |

IntentFLAG_GRANT_WRITE_URI_PERMISSION);

DocumentFile directory = DocumentFilefromTreeUri(this, directoryUri);

if (directory != null) {

listFiles(directory);

}

}

}

}

private void listFiles(DocumentFile directory) {

DocumentFile[] files = directorylistFiles();

for (DocumentFile file : files) {

Logi(TAG, "File: " + filegetName());

}

}

}

在这个示例中,我们请求存储权限,然后调用 openDirectoryPicker() 函数打开目录选择器。用户选择一个目录后,我们获取该目录的 Uri,并将其持久访问权限授予我们的应用。然后,我们使用 DocumentFile 类遍历所选目录的内容。

这个示例适用于所有 Android 版本,不需要针对特定版本编写特殊代码。请注意,通过 SAF 访问文件和目录可能比直接访问文件系统慢一些,但这是在 Android 10 及更高版本中访问外部存储的推荐方法。在低于 Android 10 的版本中,直接访问文件系统通常更快。因此,您可以选择针对低于 Android 10 的版本使用 EnvironmentgetExternalStorageDirectory(),对于 Android 10 及更高版本使用 SAF。

BitmapgetAllocationByteCount() 方法获取 Bitmap 占用的字节大小

默认情况下 BitmapFactory 使用 BitmapConfigARGB_8888 的存储方式来加载内容,而在这种存储模式下,每一个像素需要占用 4 个字节。

实际上 BitmapFactory 在解析的过程中,会根据当前设备屏幕密度和所在的 drawable 目录来做一个对比,根据这个对比值进行缩放 *** 作。

在 Android 中,各个 drawable 目录对应的屏幕密度分别为下:

PS: OptionsinMutable 置为 true,这里如果不置为 true 的话,BitmapFactory 将不会重复利用 Bitmap 内存

复用 inBitmap 之前,需要调用 canUseForInBitmap 方法来判断 reuseBitmap 是否可以被复用。这是因为 Bitmap 的复用有一定的限制:

在不压缩的前提下,不建议一次性将整张图加载到内存,而是采用分片加载的方式来显示部分内容,然后根据手势 *** 作,放大缩小或者移动显示区域。

BitmapRegionDecoder 将加载到内存中,可以以绝对路径、文件描述符、输入流的方式传递给 BitmapRegionDecoder

当需要在界面上同时展示一大堆的时候,比如 ListView、RecyclerView 等,由于用户不断地上下滑动,某个 Bitmap 可能会被短时间内加载并销毁多次。这种情况下通过使用适当的缓存,可以有效地减缓 GC 频率保证加载效率,提高界面的响应速度和流畅性。

LruCache(Least Recently Used)算法的核心思想就是 最近最少使用算法

内部维护了一个 LinkHashMap 的链表,通过put数据的时候判断是否内存已经满了,如果满了,则将最近最少使用的数据给剔除掉,从而达到内存不会爆满的状态。

以上就是关于求安卓SD存储读写实例全部的内容,包括:求安卓SD存储读写实例、Bitmap整理、等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/10057934.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-04
下一篇 2023-05-04

发表评论

登录后才能评论

评论列表(0条)

保存