设置内部sdcard存储下限

在Android中,内部存储有一部分区域是必须预留出来供系统运行应用程序的。

但是在Android原生设计中没有考虑这点,内部存储是可以完全填充满的。

这样会导致系统在运行程序,尤其是需要操作数据库的程序时,出现SQLiteFullException的错误。

解决的方法是在sdcard.c文件中加入一个限制,比如限制当存储低于100M时,不再允许第三方应用存储媒体文件。

如adb push 文件到/storage/sdcard0/中,或录音,拍照等保存到/storage/sdcard0/中。

这100M的空间专门预留出来保证系统程序的运行。

sdcard.c文件所在路径为源码中:system/core/sdcard/sdcard.c

修改完后可直接编译sdcard目录,会生成一个sdcard文件,push到系统/system/bin目录下,重启后即生效。

修改代码:

1.在sdcard.c的开始位置定义宏

// begin:SQLiteFullException happened when device memory is empty.

#define LIMIT_USEDATA_SIZE (100 * 1024 * 1024)

// end:SQLiteFullException happened when device memory is empty.

2.在fuse结构体中增加变量free_blksize
struct fuse {
   ......
    __u64 next_generation;

    // begin:SQLiteFullException happened when device memory is empty.
    __u64 free_blksize;

    // end:SQLiteFullException happened when device memory is empty.

   ......

}

3.在init方法中做初始化

static void fuse_init(struct fuse *fuse, int fd, const char *source_path,
        gid_t write_gid, derive_t derive, bool split_perms) {
    ......
    fuse->next_generation = 0;
    // begin:SQLiteFullException happened when device memory is empty.
    struct statfs stat;
    if (statfs(source_path, &stat) < 0) {
        fuse->free_blksize = 0;
    } else {
        fuse->free_blksize = stat.f_bfree * stat.f_bsize;
    }
    // end:SQLiteFullException happened when device memory is empty.

    fuse->derive = derive;

    ......

}

4.在handle_write方法中实现功能

static int handle_write(struct fuse* fuse, struct fuse_handler* handler,
        const struct fuse_in_header* hdr, const struct fuse_write_in* req,
        const void* buffer) {
    ......
    TRACE("[%d] WRITE %p(%d) %u@%llu\n", handler->token,
            h, h->fd, req->size, req->offset);
    // begin:SQLiteFullException happened when device memory is empty.
    if (!strncmp(fuse->root.name, "/data/media", fuse->root.namelen)) {
        pthread_mutex_lock(&fuse->lock);
        fuse->free_blksize -= req->size;
        pthread_mutex_unlock(&fuse->lock);

        if (fuse->free_blksize <= LIMIT_USEDATA_SIZE) {
            struct statfs stat;
            if (statfs(fuse->root.name, &stat) < 0) {
                fuse->free_blksize = 0;
                return -errno;
            } else {
                pthread_mutex_lock(&fuse->lock);
                fuse->free_blksize = stat.f_bfree * stat.f_bsize;
                pthread_mutex_unlock(&fuse->lock);
            }
            errno = ENOSPC;
            return -errno;
       }
    }
    // end:SQLiteFullException happened when device memory is empty.
    res = pwrite64(h->fd, buffer, req->size, req->offset);

    ......

}


Android原生应用中,如果需要清除SD卡的内部存储空间,通常会涉及到管理应用程序数据或者文件系统操作。这里提供一种简单的方法,但请注意,这仅适用于清除应用自身的缓存和数据: 1. **使用FileProvider** 和 `delete()` 方法: 使用`java.io.File` 和 `FileProvider.delete()` 来删除特定路径下的文件或目录。首先,确保你有权限访问SD卡,通过AndroidManifest.xml中添加 `<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />`。 ```java File cacheDirectory = new File(getExternalCacheDir(), "your_directory_name"); if (cacheDirectory.exists()) { deleteRecursively(cacheDirectory); } private void deleteRecursively(File directory) { if (!directory.isDirectory()) { directory.delete(); } else { for (File file : directory.listFiles()) { deleteRecursively(file); } directory.delete(); } } ``` 2. **使用SQLite数据库迁移工具**: 如果你需要清理数据库,可以考虑在用户卸载应用或清空数据时,创建一个新的迁移脚本,将旧的数据移动到新位置或者直接删除。 3. **使用ContentResolver API**: 对于媒体文件等,也可以使用`ContentResolver.delete()` 方法配合URI来删除特定类型的媒体文件,比如音乐、图片等。 但是,请注意,频繁地清理用户数据可能会导致用户体验变差,因此建议在用户明确请求或者应用后台运行清理任务时使用这种功能,并提供明显的提示。同时,在Android 6.0及以上版本,需要通过Storage Access Framework(SAF)获取用户的权限来操作外部存储
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值