精华内容
下载资源
问答
  • Android 保存界面状态

    2020-12-30 17:29:38
    在发生系统发起的 Activity 或应用销毁后,需要及时保存和恢复 Activity 的界面状态,这是用户体验的一个至关重要的部分。在这些情况下,用户希望界面状态保持不变,但是系统会销毁 Activity 及其中存储的任何状态。...

    在发生系统发起的 Activity 或应用销毁后,需要及时保存和恢复 Activity 的界面状态,这是用户体验的一个至关重要的部分。在这些情况下,用户希望界面状态保持不变,但是系统会销毁 Activity 及其中存储的任何状态。

    要使系统行为符合用户预期,可以把 ViewModel 对象、onSaveInstanceState() 方法和/或本地存储空间结合起来使用,从而在发生此类应用和 Activity 实例转换后保持界面状态。在决定如何组合这些选项时,需要考虑界面数据的复杂程度、应用的用例以及检索速度与内存用量的权衡。

    无论采用哪种方法,都应确保应用满足用户对其界面状态的预期,并提供流畅、简洁的界面(消除将数据载入界面过程中的延迟时间,尤其是在发生像旋转这样频繁的配置更改之后)。在大多数情况下,您应同时使用 ViewModel 和 onSaveInstanceState()。

    本页讨论了用户对界面状态的预期,可用于保留状态的选项,以及每种选项的权衡因素和局限性。

    用户预期和系统行为

    根据用户执行的操作,他们会希望系统清除或保留 Activity 状态。在某些情况下,系统会自动执行用户预期的操作。但有时,系统会执行与用户预期相反的操作。

    用户发起的界面状态解除

    用户希望当他们启动 Activity 时,该 Activity 的暂时性界面状态会保持不变,直到用户完全关闭 Activity 为止。用户可以通过以下方式完全关闭 Activity:

    • 按返回按钮
    • 从“概览”(“最近使用的应用”)屏幕中滑动关闭 Activity
    • 从 Activity 向上导航
    • 从“设置”屏幕中终止应用
    • 完成某种“完成”Activity(由 Activity.finish() 提供支持)

    在这些完全关闭的情况下,用户会认为他们已经永久离开 Activity,如果他们重新打开 Activity,会希望 Activity 以干净的状态启动。系统在这些关闭场景中的基础行为符合用户预期,即 Activity 实例将连同其中存储的任何状态以及与该 Activity 关联的任何已保存实例状态记录一起被销毁并从内存中移除。

    关于完全关闭的此规则有一些例外情况,例如用户可能希望浏览器为他们打开的是他们在使用返回按钮退出浏览器之前查看的网页。

    系统发起的界面状态解除

    用户期望 Activity 的界面状态在整个配置变更(例如旋转或切换到多窗口模式)期间保持不变。但是,默认情况下,系统会在发生此类配置更改时销毁 Activity,从而清除存储在 Activity 实例中的任何界面状态。要详细了解设备配置,请参阅配置参考页面。请注意,您可以替换针对配置更改的默认行为,但不建议这样做。如需了解详情,请参阅自行处理配置更改

    如果用户暂时切换到其他应用,稍后再返回到您的应用,他们也会希望 Activity 的界面状态保持不变。例如,用户在您的搜索 Activity 中执行搜索,然后按主屏幕按钮或接听电话,当他们返回搜索 Activity 时,希望看到搜索关键字和结果仍在原处,并和之前完全一样。

    在这种情况下,您的应用会被置于后台,系统会尽最大努力将您的应用进程留在内存中。但是,当用户转而去与其他应用进行互动时,系统可能会销毁该应用进程。在这种情况下,Activity 实例连同其中存储的任何状态都会一起被销毁。当用户重新启动应用时,Activity 会出乎意料地处于干净状态。要详细了解进程终止行为,请参阅进程和应用生命周期

    用于保留界面状态的选项

    当用户对界面状态的预期与默认系统行为不符时,您必须保存并恢复用户的界面状态,以确保系统发起的销毁对用户完全透明。

    按照以下几个会影响用户体验的维度考量,用于保留界面状态的每个选项都有所差异:

     ViewModel已保存实例状态持久性存储空间
    存储位置在内存中已序列化到磁盘在磁盘或网络上
    在配置更改后继续存在
    在系统发起的进程终止后继续存在
    在用户完成 Activity 关闭/onFinish() 后继续存在
    数据限制支持复杂对象,但是空间受可用内存的限制仅适用于基元类型和简单的小对象,例如字符串仅受限于磁盘空间或从网络资源检索的成本/时间
    读取/写入时间快(仅限内存访问)慢(需要序列化/反序列化和磁盘访问)慢(需要磁盘访问或网络事务)

    使用 ViewModel 处理配置更改

    ViewModel 非常适合在用户正活跃地使用应用时存储和管理界面相关数据。它支持快速访问界面数据,并且有助于避免在发生旋转、窗口大小调整和其他常见的配置更改后从网络或磁盘中重新获取数据。要了解如何实现 ViewModel,请参阅 ViewModel 指南

    ViewModel 将数据保留在内存中,这意味着成本要低于从磁盘或网络检索数据。ViewModel 与一个 Activity(或其他生命周期所有者)相关联,在配置更改期间保留在内存中,系统会自动将 ViewModel 与发生配置更改后产生的新 Activity 实例相关联。

    当用户退出您的 Activity 或 Fragment 时,或者在您调用 finish() 的情况下,系统会自动销毁 ViewModel,这意味着状态会被清除,正如用户在这些场景中所预期的一样。

    与已保存实例状态不同,ViewModel 在系统发起的进程终止过程中会被销毁。因此,您应将 ViewModel 对象与 onSaveInstanceState()(或其他一些磁盘持久性功能)结合使用,并将标识符存储在 savedInstanceState 中,以帮助视图模型在系统终止后重新加载数据。

    如果您已有用于在发生配置更改后存储界面状态的内存中解决方案,则可能不需要使用 ViewModel。

    使用 onSaveInstanceState() 作为后备方法来处理系统发起的进程终止

    onSaveInstanceState() 回调会存储一些数据,如果系统销毁后又重新创建界面控制器(如 Activity 或 Fragment),则需要使用这些数据重新加载该控制器的状态。要了解如何实现已保存实例状态,请参阅 Activity 生命周期指南中的“保存和恢复 Activity 状态”。

    已保存实例状态捆绑包在配置更改和进程终止后都会保留,但受限于存储容量和速度,因为 onSavedInstanceState() 会将数据序列化到磁盘。如果序列化的对象很复杂,序列化会占用大量的内存。因为此过程在配置更改期间发生在主线程上,所以如果耗时太长,序列化可能会导致丢帧和视觉卡顿。

    请勿将 onSavedInstanceState() 用于存储大量的数据(如位图),也不要用于存储需要冗长的序列化或反序列化操作的复杂数据结构,而是只能用于存储基本类型和简单的小对象,例如字符串。因此,请使用 onSaveInstanceState() 存储最少量的数据(例如 ID),如果其他持久性机制失效,需要使用这些数据来重新创建必要的数据以将界面恢复到之前的状态。大多数应用都应实现 onSaveInstanceState() 来处理系统发起的进程终止。

    根据应用的用例,您可能完全不需要使用 onSaveInstanceState()。例如,浏览器可能会将用户带回他们在退出浏览器之前正在查看的确切网页。如果 Activity 表现出这种行为,您可以放弃使用 onSaveInstanceState(),改为在本地保留所有内容。

    此外,如果您从 intent 打开 Activity,当配置发生更改以及系统恢复该 Activity 时,会将 extra 捆绑包传送给该 Activity。在 Activity 启动时,如果一段界面状态数据(例如搜索查询)作为 intent extra 传入,则您可以使用 extra 捆绑包而不是 onSaveInstanceState() 捆绑包。如需详细了解 intent extra,请参阅 intent 和 intent 过滤器

    在上述任一情况下,您仍然可以使用 ViewModel 来避免因在配置更改期间从数据库重新加载数据而浪费周期时间。

    如果要保留的是简单的轻量级界面数据,那么您可以单独使用 onSaveInstanceState() 来保留状态数据。

    注意:您现在可以通过 ViewModel 的已保存状态模块(目前为 Alpha 版)在 ViewModel 对象中提供对已保存状态的访问途径。已保存状态可通过 SavedStateHandle 对象来访问。您可以在 Android 生命周期感知型组件 Codelab 中查看其使用方式。

    针对复杂或大型数据使用本地持久性存储来处理进程终止

    只要您的应用安装在用户的设备上,持续性本地存储(例如数据库或共享偏好设置)就会继续存在(除非用户清除应用的数据)。虽然此类本地存储空间会在系统启动的活动和应用进程终止后继续存在,但由于必须从本地存储空间读取到内存,因此检索成本高昂。这种持久性本地存储通常已经属于应用架构的一部分,用于存储您打开和关闭 Activity 时不想丢失的所有数据。

    ViewModel 和已保存实例状态均不是长期存储解决方案,因此不能替代本地存储空间,例如数据库。您只应该使用这些机制来暂时存储瞬时界面状态,对于其他应用数据,应使用持久性存储空间。请参阅应用架构指南,详细了解如何充分利用本地存储空间长期保留您的应用模型数据(例如在重启设备后)。

    管理界面状态:分而治之

    您可以通过在各种类型的持久性机制之间划分工作,高效地保存和恢复界面状态。在大多数情况下,这些机制中的每一种都应存储 Activity 中使用的不同类型的数据,具体取决于数据复杂度、访问速度和生命周期的权衡:

    • 本地持久性存储:存储在您打开和关闭 Activity 时不希望丢失的所有数据。
      • 示例:歌曲对象的集合,其中可能包括音频文件和元数据。
    • ViewModel:在内存中存储显示关联界面控制器所需的所有数据。
      • 示例:最近搜索的歌曲对象和最近的搜索查询。
    • onSaveInstanceState():存储当系统停止后又重新创建界面控制器时轻松重新加载 Activity 状态所需的少量数据。这里指的是将复杂的对象保留在本地存储空间中,并将这些对象的唯一 ID 存储在 onSaveInstanceState()中,而不是存储复杂的对象。
      • 示例:存储最近的搜索查询。

    例如,假设有一个用于搜索歌曲库的 Activity。应按如下方式处理不同的事件:

    当用户添加歌曲时,ViewModel 会立即委托在本地保留此数据。如果新添加的这首歌曲应显示在界面中,则您还应更新 ViewModel 对象中的数据以表明该歌曲已添加。切记在主线程以外执行所有数据库插入操作。

    当用户搜索歌曲时,针对界面控制器从数据库加载的任何复杂歌曲数据都应立即存储在 ViewModel 对象中。您还应将搜索查询本身保存在 ViewModel 对象中。

    当 Activity 进入后台时,系统会调用 onSaveInstanceState()。您应将搜索查询保存在 onSaveInstanceState() 捆绑包中。该少量数据很容易保存。这也是使 Activity 恢复到当前状态所需的所有信息。

    恢复复杂的状态:重组碎片

    当到了用户该返回 Activity 的时候,重新创建 Activity 存在两种可能情况:

    • 在系统停止 Activity 后重新创建该 Activity。该 Activity 将查询保存在 onSaveInstanceState() 捆绑包中,并且应将查询传递给 ViewModelViewModel 发现它没有缓存搜索结果,并使用指定的搜索查询委托加载搜索结果。
    • 在配置更改后创建 Activity。该 Activity 将查询保存在 onSaveInstanceState() 捆绑包中,而且 ViewModel 已缓存搜索结果。您将查询从 onSaveInstanceState() 捆绑包传递到 ViewModel,以此确定它已加载必要的数据,且无需从数据库重新查询数据。

    注意:最初创建 Activity 时,onSaveInstanceState() 捆绑包不包含任何数据,且 ViewModel 对象为空。创建 ViewModel对象时,您将传递空白查询,以此告知 ViewModel 对象尚没有要加载的数据。因此,Activity 以空状态启动。

    展开全文
  • Android保存图像到相册

    2021-03-14 02:39:24
    在应用的图集中,通常会给用户提供保存图片的功能,让用户可以将自己喜欢的图片保存到系统相册中.这个功能其实很好做,系统提供了现成的API:简单的来说就这一行代码:[java]MediaStore.Images.Media.insertImage...

    在应用的图集中,通常会给用户提供保存图片的功能,让用户可以将自己喜欢的图片保存到系统相册中.

    这个功能其实很好做,系统提供了现成的API:

    简单的来说就这一行代码:

    [java]  MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");

    MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");

    这个方法的返回值及为插入图片的路径

    [java]  String url = MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");

    String url = MediaStore.Images.Media.insertImage(getContentResolver(), mBitmap, "", "");

    但是在很多机器(比如G7,G11)上调用之后,进入相册并看不到刚才保存的那张图片,需要将机器重启后在系统相册中才会显示出来,大大影响了用户体验

    这是由于机器系统缓存的问题.需要我们在插入图片之后往刷新下相册环境:

    这里有两种方法:

    [java]

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory())));

    或者:

    [java]

    final MediaScannerConnection msc = new MediaScannerConnection(mContext, new MediaScannerConnectionClient() {

    public void onMediaScannerConnected() {

    msc.scanFile("/sdcard/image.jpg", "image/jpeg");

    }

    public void onScanCompleted(String path, Uri uri) {

    msc.disconnect();

    }

    });

    final MediaScannerConnection msc = new MediaScannerConnection(mContext, new MediaScannerConnectionClient() {

    public void onMediaScannerConnected() {

    msc.scanFile("/sdcard/image.jpg", "image/jpeg");

    }

    public void onScanCompleted(String path, Uri uri) {

    msc.disconnect();

    }

    }); 这里要注意的是,发送广播或者直接调用扫描整个SD卡,实际上效率会比较低,也会增加耗电量.

    上面提到,插入图片的方法对应的返回值为图片保存的绝对路径. 因此我们只要获取该路径,发送广播扫描该路径即可.

    [java]

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()+ picPath)));

    sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://"+ Environment.getExternalStorageDirectory()+ picPath)));

    展开全文
  • 在做项目的时候难免需要保存一下配置文件,我们经常使用的就是SharedPreferences,但是当我们清除掉缓存或者卸载后重新安装这些配置文件内容就不存在了,当我们想卸载后重新安装这些配置文件还在,那只能将这些配置...

    在做项目的时候难免需要保存一下配置文件,我们经常使用的就是SharedPreferences,但是当我们清除掉缓存或者卸载后重新安装这些配置文件内容就不存在了,当我们想卸载后重新安装这些配置文件还在,那只能将这些配置文件保存到本地了,用的时候去读取,保存本地有两种,保存为TXT或者是保存为xml

    第一种:把配置文件保存为TXT到本地

    1、我们需要一个操作文件的工具类,这里已经写好

    import android.graphics.Bitmap;
    import android.os.Environment;
    
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.RandomAccessFile;
    
    /**
     * date : 2021/4/23 2:05 PM
     * description :文件工具类
     */
    public class FileUtils {
        /**
         * 读取txt文件的内容
         *
         * @param filePath 想要读取的文件对象
         * @return 返回文件内容
         */
        public static String txt2String(String filePath) {
            File file = new File(filePath);
            if (!file.exists()) {
                return "";
            }
    
            StringBuilder result = new StringBuilder();
            try {
                // 构造一个BufferedReader类来读取文件
                BufferedReader br = new BufferedReader(new FileReader(file));
                String s = null;
                // 使用readLine方法,一次读一行
                while ((s = br.readLine()) != null) {
                    result.append(System.lineSeparator() + s);
                }
                br.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result.toString();
        }
    
    
        /**
         * 写入TXT文件
         */
        public static boolean writeTxtFile(String content, String filePath) {
            File file = new File(filePath);
            if (!file.exists()) {
                return false;
            }
    
            RandomAccessFile mm = null;
            boolean flag = false;
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write(content.getBytes("utf-8"));
                fileOutputStream.close();
                flag = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return flag;
        }
    
        /**
         * Checks if is sd card available.检查SD卡是否可用
         */
        public static boolean isSdCardAvailable() {
            return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        }
    
        /**
         * Gets the SD root file.获取SD卡根目录
         */
        public static File getSDRootFile() {
            if (isSdCardAvailable()) {
                return Environment.getExternalStorageDirectory();
            } else {
                return null;
            }
        }
    
        /**
         * 获取导入图片文件的目录信息
         */
        public static File getBatchImportDirectory() {
            // 获取根目录
            File sdRootFile = getSDRootFile();
            File file = null;
            if (sdRootFile != null && sdRootFile.exists()) {
                file = new File(sdRootFile, "Face-Import");
                if (!file.exists()) {
                    file.mkdirs();
                }
            }
            return file;
        }
    
        /**
         * 获取导入图片成功的目录信息
         */
        public static File getBatchImportSuccessDirectory() {
            File sdRootFile = getSDRootFile();
            File file = null;
            if (sdRootFile != null && sdRootFile.exists()) {
                file = new File(sdRootFile, "Success-Import");
                if (!file.exists()) {
                    file.mkdirs();
                }
            }
            return file;
        }
    
        /**
         * 判断文件是否存在
         */
        public static File isFileExist(String fileDirectory, String fileName) {
            File file = new File(fileDirectory + "/" + fileName);
            try {
                if (!file.exists()) {
                    return null;
                }
            } catch (Exception e) {
                return null;
            }
            return file;
        }
    
        /**
         * 删除文件
         */
        public static void deleteFile(String filePath) {
            try {
                // 找到文件所在的路径并删除该文件
                File file = new File(filePath);
                file.delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /*
         * 获取不带扩展名的文件名
         * */
        public static String getFileNameNoEx(String filename) {
            if ((filename != null) && (filename.length() > 0)) {
                int dot = filename.lastIndexOf('.');
                if ((dot > -1) && (dot < (filename.length()))) {
                    return filename.substring(0, dot);
                }
            }
            return filename;
        }
    
        /**
         * 保存图片
         */
        public static boolean saveBitmap(File file, Bitmap bitmap) {
            FileOutputStream out = null;
            try {
                out = new FileOutputStream(file);
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return false;
        }
    
        public static boolean copyFile(String oldPath, String newPath) {
            InputStream inStream = null;
            FileOutputStream fs = null;
            boolean result = false;
            try {
                int bytesum = 0;
                int byteread = 0;
                File oldfile = new File(oldPath);
                // 判断目录是否存在
                File newfile = new File(newPath);
                File newFileDir = new File(newfile.getPath().replace(newfile.getName(), ""));
                if (!newFileDir.exists()) {
                    newFileDir.mkdirs();
                }
                if (oldfile.exists()) { // 文件存在时
                    inStream = new FileInputStream(oldPath); // 读入原文件
                    fs = new FileOutputStream(newPath);
                    byte[] buffer = new byte[1444];
                    int length;
                    while ((byteread = inStream.read(buffer)) != -1) {
                        bytesum += byteread; // 字节数 文件大小
                        System.out.println(bytesum);
                        fs.write(buffer, 0, byteread);
                    }
                    result = true;
                } else {
                    result = false;
                }
            } catch (Exception e) {
                System.out.println("复制单个文件操作出错");
                e.printStackTrace();
            } finally {
                if (inStream != null) {
                    try {
                        inStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fs != null) {
                    try {
                        fs.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return result;
        }
    
    }
    

    2,、需要一个保存读取文件的工具类,同时检测文件是否存在,文件里面是否有内容等

    
    import android.os.Environment;
    import android.util.Log;
    import org.json.JSONObject;
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.lang.reflect.Field;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    /**
     * Created by Forrest.
     * User: Administrator
     * Date: 2021/5/7
     * Description:
     */
    public class SaveConfigUtils {
        //设置gateFaceConfig的根路径
        public static final String folder = Environment.getExternalStorageDirectory() + File.separator + "Settings";
    
        // 配置文件路径
        public static final String filePath = folder + "/" + "Ceshi.txt";
    
        //判断文件是否存在
        public static boolean isConfigExit() {
            File file1 = new File(folder);
            //判断Settings文件夹是否存在
            if (!file1.exists()) {
                file1.mkdirs();
            }
            //判断gateFaceConfig.txt文件是否存在,存在返回true,不存在创建文件并更新文件
            File file = new File(filePath);
            if (file.exists()) {
                return true;
            } else {
                try {
                    file.createNewFile();
                    modityJson();
                } catch (IOException e) {
                    e.printStackTrace();
                    return false;
                }
                return true;
            }
        }
    
        public static String configMessage() {
            String configMessage = FileUtils.txt2String(filePath);
            return configMessage;
        }
    
        /**
         * 判断SDCard是否可用
         *
         * @return
         */
        public static boolean isSDCardEnable() {
            return Environment.getExternalStorageState().equals(
                    Environment.MEDIA_MOUNTED);
        }
    
        /**
         * 读取配置文件内容
         *
         * @return
         */
        public static Boolean initConfig() {
            //得到gateFaceConfig.txt文件里面的内容
            String configMessage = FileUtils.txt2String(filePath);
            //gateFaceConfig.txt里面的内容为空返回false
            if (configMessage.equals("")) {
                Log.e("facesdk", "文件不存在");
                return false;
            }
            //gateFaceConfig.txt里面的内容不为空就为SingleBaseConfig赋值
            Log.e("人脸识别", filePath + "文件存在" + configMessage);
            JSONObject jsonObject = null;
            try {
                jsonObject = new JSONObject(configMessage);
                if (!identify(jsonObject)) {
                    return false;
                }
                SingleBaseConfig.getBaseConfig().setName(jsonObject.getString("name"));// RGB检测帧回显
                SingleBaseConfig.getBaseConfig().setSex(jsonObject.getString("sex"));// NIR或depth实时视频预览
                SingleBaseConfig.getBaseConfig().setAge(jsonObject.getString("age"));// 默认为false。可选项为"true"、"false",是否开启调试显示,将会作用到所有视频流识别页面,包含1:N、1:1采集人脸图片环节。
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                Log.e("facesdk", "文件内容异常,请检测是否规范");
                return false;
            }
        }
    
        // 校验sdcard里的txt文件内容是否正常
        public static boolean identify(JSONObject jsonObject) {
            try {
                Boolean display = (Boolean) jsonObject.get("display");
                Boolean isNirOrDepth = (Boolean) jsonObject.get("isNirOrDepth");
    
                Boolean debug = (Boolean) jsonObject.get("debug");
                int videoDirection = Integer.parseInt(jsonObject.getString("videoDirection"));
                if (!(videoDirection == 0 || videoDirection == 90 || videoDirection == 180 || videoDirection == 270)) {
                    return false;
                }
                String detectFrame = (String) jsonObject.get("detectFrame");
                if (!(detectFrame.equals("wireframe") || detectFrame.equals("fixedarea"))) {
                    return false;
                }
    
    //            int radius = (int) jsonObject.get("radius");
    
                int detectDirection = (int) jsonObject.get("detectDirection");
                if (!(detectDirection == 0 || detectDirection == 90 || detectDirection == 180
                        || detectDirection == 270)) {
                    return false;
                }
    
                String trackType = (String) jsonObject.get("trackType");
                if (!(trackType.equals("max") || trackType.equals("first") || trackType.equals("none"))) {
                    return false;
                }
    
                int minimumFace = (int) jsonObject.get("minimumFace");
                if (minimumFace < 30) {
                    return false;
                }
    
                float blur = Float.valueOf(jsonObject.get("blur") + "");
                if (blur > 1 || blur < 0) {
                    return false;
                }
    
                int illumination = (int) jsonObject.get("illumination");
                if (illumination < 0 || illumination > 255) {
                    return false;
                }
    
                float gesture = Float.valueOf(jsonObject.get("gesture") + "");
    
                float pitch = Float.valueOf(jsonObject.get("pitch") + "");
                if (pitch < -90 || pitch > 90) {
                    return false;
                }
    
                float roll = Float.valueOf(jsonObject.get("roll") + "");
                if (roll < -90 || roll > 90) {
                    return false;
                }
    
                float yaw = Float.valueOf(jsonObject.get("yaw") + "");
                if (yaw < -90 || yaw > 90) {
                    return false;
                }
    
                float occlusion = Float.valueOf(jsonObject.get("occlusion") + "");
                if (occlusion < 0 || occlusion > 1) {
                    return false;
                }
    
    
                float leftEye = Float.valueOf(jsonObject.get("leftEye") + "");
                if (leftEye < 0 || leftEye > 1) {
                    return false;
                }
    
                float rightEye = Float.valueOf(jsonObject.get("rightEye") + "");
                if (rightEye < 0 || rightEye > 1) {
                    return false;
                }
    
                float nose = Float.valueOf(jsonObject.get("nose") + "");
                if (nose < 0 || nose > 1) {
                    return false;
                }
    
                float mouth = Float.valueOf(jsonObject.get("mouth") + "");
                if (mouth < 0 || mouth > 1) {
                    return false;
                }
    
                float leftCheek = Float.valueOf(jsonObject.get("leftCheek") + "");
                if (leftCheek < 0 || leftCheek > 1) {
                    return false;
                }
    
                float rightCheek = Float.valueOf(jsonObject.get("rightCheek") + "");
                if (rightCheek < 0 || rightCheek > 1) {
                    return false;
                }
    
                float chinContour = Float.valueOf(jsonObject.get("chinContour") + "");
                if (chinContour < 0 || chinContour > 1) {
                    return false;
                }
    
                float completeness = Float.valueOf(jsonObject.get("completeness") + "");
                if (completeness < 0 || completeness > 1) {
                    return false;
                }
                int rgbAndNirThreshold = Integer.valueOf(jsonObject.get("rgbAndNirThreshold") + "");
                if (rgbAndNirThreshold < 0 || rgbAndNirThreshold > 100) {
                    return false;
                }
    
                int cameraLightThreshold = Integer.valueOf(jsonObject.get("cameraLightThreshold") + "");
                if (cameraLightThreshold < 0 || cameraLightThreshold > 100) {
                    return false;
                }
    
                int liveThreshold = Integer.valueOf(jsonObject.get("liveThreshold") + "");
                if (liveThreshold < 0 || liveThreshold > 100) {
                    return false;
                }
    
                int idThreshold = Integer.valueOf(jsonObject.get("IdThreshold") + "");
                if (idThreshold < 0 || idThreshold > 100) {
                    return false;
                }
    
                int activeModel = Integer.valueOf(jsonObject.get("activeModel") + "");
                if (!(activeModel == 1 || activeModel == 2 || activeModel == 3)) {
                    return false;
                }
    
                int timeLapse = Integer.valueOf(jsonObject.get("timeLapse") + "");
    
                int type = Integer.valueOf(jsonObject.get("type") + "");
                if (!(type == 0 || type == 1 || type == 2 || type == 3 || type == 4)) {
                    return false;
                }
    
                float rgbLiveScore = Float.valueOf(jsonObject.get("rgbLiveScore") + "");
                if (rgbLiveScore < 0 || rgbLiveScore > 1) {
                    return false;
                }
    
                float nirLiveScore = Float.valueOf(jsonObject.get("nirLiveScore") + "");
                if (nirLiveScore < 0 || nirLiveScore > 1) {
                    return false;
                }
    
                float depthLiveScore = Float.valueOf(jsonObject.get("depthLiveScore") + "");
                if (depthLiveScore < 0 || depthLiveScore > 1) {
                    return false;
                }
                int cameraType = jsonObject.getInt("cameraType");
                if (!(cameraType == 0 || cameraType == 1 || cameraType == 2 || cameraType == 3 ||
                        cameraType == 4 || cameraType == 5 || cameraType == 6)) {
                    return false;
                }
    
                int mirrorRGB = jsonObject.getInt("mirrorRGB");
                if (!(mirrorRGB == 0 || mirrorRGB == 1)) {
                    return false;
                }
    
                int mirrorNIR = jsonObject.getInt("mirrorNIR");
                if (!(mirrorNIR == 0 || mirrorNIR == 1)) {
                    return false;
                }
    
                int getBestImageScore = jsonObject.getInt("bestImageScore");
                if (getBestImageScore < 0 || getBestImageScore > 100) {
                    return false;
                }
    
                int rgbAndNirWidth = jsonObject.getInt("rgbAndNirWidth");
                int rgbAndNirHeight = jsonObject.getInt("rgbAndNirHeight");
                int depthWidth = jsonObject.getInt("depthWidth");
                int depthHeight = jsonObject.getInt("depthHeight");
    
            } catch (Exception e) {
                String errorMessage = getErrorInfoFromException(e);
                e.printStackTrace();
                Log.e("facesdk", "文件内容格式异常,请检测是否规范");
                return false;
            }
    
            return true;
        }
    
        /**
         * 修改配置文件内容并重新读取配置
         */
        public static boolean modityJson() {
    
            JSONObject jsonObject = new JSONObject();
    
            try {
                jsonObject.put("name", SingleBaseConfig.getBaseConfig().getName());
                jsonObject.put("sex", SingleBaseConfig.getBaseConfig().getSex());
                jsonObject.put("age", SingleBaseConfig.getBaseConfig().getAge());
    
                // 修改内容写入配置文件
                FileUtils.writeTxtFile(jsonObject.toString(), filePath);
                // 重新读取配置文件内容
                initConfig();
    
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        public static String getErrorInfoFromException(Exception e) {
            try {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                return "\r\n" + sw.toString() + "\r\n";
            } catch (Exception e2) {
                return "bad getErrorInfoFromException";
            }
        }
    
        /**
         * 判断数字正则表达式
         *
         * @param str
         * @return
         */
        public boolean isNumeric(String str) {
            Pattern pattern = Pattern.compile("[0-9]");
            Matcher isNum = pattern.matcher(str);
            if (!isNum.matches()) {
                return false;
            }
            return true;
    
        }
    
        /**
         * 判断字符正则表达式
         *
         * @param str
         * @return
         */
        public boolean isString(String str) {
    
            return str.matches("[a-zA-Z]+");
    
        }
    
    
        // 对象属性赋值
        public static <T> T gotObjectByObject(Object object, Class<T> clazz) throws Exception {
            T t = null;
            if (clazz != null && object != null) {
                t = clazz.newInstance();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    String key = field.getName();
                    try {
                        Field field1 = object.getClass().getDeclaredField(key);
                        field1.setAccessible(true);
                        Object val = field1.get(object);
                        field.set(t, val);
                    } catch (Exception e) {
                        t = null;
                        System.out.println(object.getClass().getName() + "没有该属性: " + key);
                    }
                }
            }
            return t;
        }
    }
    

    3、配置一下需要保存的参数

    
    /**
     * Created by Forrest.
     * User: Administrator
     * Date: 2021/5/7
     * Description:
     */
    public class FileConfig {
        private String name="张三";
        private String sex="男";
        private String age="12";
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAge() {
            return age;
        }
    
        public void setAge(String age) {
            this.age = age;
        }
    }
    

    4、配置FileConfig为单例

    
    /**
     * date : 2021/4/23 11:23 AM
     * description :配置BaseConfig单例
     */
    public class SingleBaseConfig {
        private static FileConfig baseConfig;
    
        private SingleBaseConfig() {
    
        }
    
        public static FileConfig getBaseConfig() {
            if (baseConfig == null) {
                baseConfig = new FileConfig();
            }
            return baseConfig;
        }
    
        public static void copyInstance(FileConfig result) {
            baseConfig = result;
        }
    }

    5、然后就是保存和读取的操作了

    @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_savetxt:
                    SingleBaseConfig.getBaseConfig().setName(mEtName.getText().toString());
                    SingleBaseConfig.getBaseConfig().setSex(mEtSex.getText().toString());
                    SingleBaseConfig.getBaseConfig().setAge(mEtAge.getText().toString());
                    SaveConfigUtils.modityJson();
                    break;
                case R.id.btn_readtxt:
                    String name = SingleBaseConfig.getBaseConfig().getName();
                    String sex = SingleBaseConfig.getBaseConfig().getSex();
                    String age = SingleBaseConfig.getBaseConfig().getAge();
                    mTvShowtxt.setText(SaveConfigUtils.configMessage());
                    Log.e("Ceshi文件", "name=" + name);
                    Log.e("Ceshi文件", "sex=" + sex);
                    Log.e("Ceshi文件", "age=" + age);
                    break;
              
            }
        }

    第二种、把配置文件保存为xml到本地

    1、保存方法

        /**
         * 保存配置文件到本地
         */
        public void setConfig() {
            try {
                File file = new File(Environment.getExternalStorageDirectory() + File.separator + "Settings", "Ceshi.xml");
                Log.e(TAG, "" + file);
                FileOutputStream fos = new FileOutputStream(file);
                // 获得一个序列化工具
                XmlSerializer serializer = Xml.newSerializer();
                serializer.setOutput(fos, "utf-8");
                // 设置文件头
                serializer.startDocument("utf-8", true);
                serializer.startTag(null, "persons");
                serializer.startTag(null, "person");
                serializer.attribute(null, "id", String.valueOf(0));
                // TODO 写入姓名
                serializer.startTag(null, "name");
                serializer.text(mEtName.getText().toString());
                serializer.endTag(null, "name");
                // TODO 写入性别
                serializer.startTag(null, "sex");
                serializer.text(mEtSex.getText().toString());
                serializer.endTag(null, "sex");
                // TODO 写入年纪
                serializer.startTag(null, "age");
                serializer.text(mEtAge.getText().toString());
                serializer.endTag(null, "age");
    
                serializer.endTag(null, "person");
                serializer.endTag(null, "persons");
                serializer.endDocument();
                fos.close();
                Toast.makeText(SaveConfigActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
            } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(SaveConfigActivity.this, "保存失败", Toast.LENGTH_SHORT).show();
            }
        }

    2、读取方法

        /**
         * 读取本地配置文件
         */
        public void getConfig() {
            try {
                File path = new File(Environment.getExternalStorageDirectory() + File.separator + "Settings", "Ceshi.xml");
                FileInputStream fis = new FileInputStream(path);
    
                // 获得pull解析器对象
                XmlPullParser parser = Xml.newPullParser();
                // 指定解析的文件和编码格式
                parser.setInput(fis, "utf-8");
    
                int eventType = parser.getEventType(); // 获得事件类型
    
                String id = null;
                String name = null;
                String sex = null;
                String age = null;
    
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    String tagName = parser.getName(); // 获得当前节点的名称
    
                    switch (eventType) {
                        case XmlPullParser.START_TAG: // 当前等于开始节点 <person
                            if ("persons".equals(tagName)) { // <persons
                            } else if ("person".equals(tagName)) { // <person id="1"
                                id = parser.getAttributeValue(null, "id");
                            } else if ("name".equals(tagName)) { // <versioncode
                                name = parser.nextText();
                            } else if ("sex".equals(tagName)) { // <soakingvoice
                                sex = parser.nextText();
                            } else if ("age".equals(tagName)) { // <voiceprompt
                                age = parser.nextText();
                            }
                            break;
                        case XmlPullParser.END_TAG: // </persons
                            if ("person".equals(tagName)) {
                                Log.e(TAG, "id---" + id);
                                Log.e(TAG, "name---" + name);
                                Log.e(TAG, "sex---" + sex);
                                Log.e(TAG, "age---" + age);
                                mTvShowxml.setText("name:" + name + "\rsex:" + sex + "\rage:" + age);
                            }
                            break;
                        default:
                            break;
                    }
                    eventType = parser.next(); // 获得下一个事件类型
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
    
            }
        }

    两种方法都可以保存配置文件到本地,另外SharedPreferences现在已经被mmvk所代替,下面介绍下mmvk的使用方法

    mmvk

    1、添加依赖

    implementation 'com.tencent:mmkv-static:1.0.23'

    2、添加Application配置,放到onCreate里面

    //缓存的文件在Settings文件夹下的mmvk文件夹
    String dir = Environment.getExternalStorageDirectory() + File.separator + "Settings"+"/mmvk";
    MMKV.initialize(dir);
    SpUtils.getInstance();

    3、使用方法

    //保存
    SpUtils.encode("int",10);
    SpUtils.encode("bool",false);
    SpUtils.encode("long",10);
    SpUtils.encode("float",10.f);
    SpUtils.encode("double",10.5);
    SpUtils.encode("string","10");
    byte[] bytes = {'m', 'm', 'k', 'v'};
    SpUtils.encode("bytes",bytes);
    //读取
    LogUtils.e(SpUtils.decodeInt("int"));
    LogUtils.e(SpUtils.decodeBoolean("bool"));
    LogUtils.e(SpUtils.decodeLong("long"));
    LogUtils.e(SpUtils.decodeFloat("float"));
    LogUtils.e(SpUtils.decodeDouble("double"));
    LogUtils.e(SpUtils.decodeString("string"));
    LogUtils.e(SpUtils.decodeBytes("bytes"));
    package com.dhy.health.saveconfig;
    
    import android.os.Parcelable;
    
    import com.tencent.mmkv.MMKV;
    
    import java.util.Collections;
    import java.util.Set;
    
    /**
     * Created by Forrest.
     * User: Administrator
     * Date: 2021/3/25
     * Description:
     */
    public class SpUtils {
    
        private static SpUtils mInstance;
        private static MMKV mv;
    
        private SpUtils() {
            mv = MMKV.defaultMMKV();
        }
    
        /**
         * 初始化MMKV,只需要初始化一次,建议在Application中初始化
         *
         */
        public static SpUtils getInstance() {
            if (mInstance == null) {
                synchronized (SpUtils.class) {
                    if (mInstance == null) {
                        mInstance = new SpUtils();
                    }
                }
            }
            return mInstance;
        }
    
        /**
         * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
         *
         * @param key
         * @param object
         */
        public static void encode(String key, Object object) {
            if (object instanceof String) {
                mv.encode(key, (String) object);
            } else if (object instanceof Integer) {
                mv.encode(key, (Integer) object);
            } else if (object instanceof Boolean) {
                mv.encode(key, (Boolean) object);
            } else if (object instanceof Float) {
                mv.encode(key, (Float) object);
            } else if (object instanceof Long) {
                mv.encode(key, (Long) object);
            } else if (object instanceof Double) {
                mv.encode(key, (Double) object);
            } else if (object instanceof byte[] ) {
                mv.encode(key, (byte[]) object);
            } else {
                mv.encode(key, object.toString());
            }
        }
    
        public static void encodeSet(String key, Set<String> sets) {
            mv.encode(key, sets);
        }
    
        public static void encodeParcelable(String key, Parcelable obj) {
            mv.encode(key, obj);
        }
    
    
        /**
         * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
         */
        public static Integer decodeInt(String key) {
            return mv.decodeInt(key, 0);
        }
        public static Double decodeDouble(String key) {
            return mv.decodeDouble(key, 0.00);
        }
        public static Long decodeLong(String key) {
            return mv.decodeLong(key, 0L);
        }
        public static Boolean decodeBoolean(String key) {
            return mv.decodeBool(key, false);
        }
        public static Float decodeFloat(String key) {
            return mv.decodeFloat(key, 0F);
        }
        public static byte[] decodeBytes(String key) {
            return mv.decodeBytes(key);
        }
        public static String decodeString(String key) {
            return mv.decodeString(key,"");
        }
        public static Set<String> decodeStringSet(String key) {
            return mv.decodeStringSet(key, Collections.<String>emptySet());
        }
        public static Parcelable decodeParcelable(String key) {
            return mv.decodeParcelable(key, null);
        }
        /**
         * 移除某个key对
         *
         * @param key
         */
        public static void removeKey(String key) {
            mv.removeValueForKey(key);
        }
        /**
         * 清除所有key
         */
        public static void clearAll() {
            mv.clearAll();
        }
    
    }
    

    项目地址,需要的加自行下载:SaveConfig.rar_android可修改的配置写入配置文件还是txt好-互联网文档类资源-CSDN下载

    展开全文
  • sd卡用于保存大文件如视频,音频,大文档等package cn.itcast.files;import cn.itcast.service.FileService;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android....

    sd卡用于保存大文件如视频,音频,大文档等

    package cn.itcast.files;

    import cn.itcast.service.FileService;

    import android.app.Activity;

    import android.os.Bundle;

    import android.os.Environment;

    import android.view.View;

    import android.widget.Button;

    import android.widget.EditText;

    import android.widget.Toast;

    public class MainActivity extends Activity {

    /** Called when the activity is first created. */

    @Override

    public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    Button button = (Button) this.findViewById(R.id.button);

    button.setOnClickListener(new ButtonClickListener());

    }

    private final class ButtonClickListener implements View.OnClickListener{

    /*

    * 内部类如果不需要被继承要使用final修饰

    *

    * */

    public void onClick(View v) {

    EditText filenameText = (EditText) findViewById(R.id.filename);

    EditText contentText = (EditText) findViewById(R.id.filecontent);

    String filename = filenameText.getText().toString();

    String content = contentText.getText().toString();

    FileService service = new FileService(getApplicationContext());

    try {

    /*

    *

    * 判断SDCard是否存在,是否可以读写

    * 因为部分手机没有SD卡,或者sd卡有写入保护

    *

    * 使用Environment类的getExternalStorageState()方法获取sd卡的状态

    * Environment.MEDIA_MOUNTED该常量代表sd卡存在并且可以读写

    *

    * */

    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

    service.saveToSDCard(filename, content);

    Toast.makeText(getApplicationContext(), R.string.success, 1).show();

    }else{

    Toast.makeText(getApplicationContext(), R.string.sdcarderror, 1).show();

    }

    } catch (Exception e) {

    Toast.makeText(getApplicationContext(), R.string.fail, 1).show();

    e.printStackTrace();

    }

    }

    }

    }

    public class FileService {

    /*

    * 文件保存属于业务层,根据MVC模式的思想

    * 这里写了一个专门的FileSarvie类处理文件保存的操作

    * */

    private Context context;

    public FileService(Context context) {

    this.context = context;

    }

    public void saveToSDCard(String filename, String content)throws Exception {

    /*

    * 保存文件到sd卡,sd卡用于保存大文件(视频,音乐,文档等)

    * 获取sd卡路径Environment.getExternalStorageDirectory()

    * android版本不同,sd卡的路径也不相同,所以这里不能写绝对路径

    * */

    File file = new File(Environment.getExternalStorageDirectory(), filename);

    FileOutputStream outStream = new FileOutputStream(file);

    /**

    *

    * 注意:这里创建文件输出流对象 就 不能使用context.openFileOutput(filename, Context.MODE_PRIVATE);这中方式创建了这种方式会直接在手机自带的内存中创建文件,

    在sd卡下创建文件要使用new FileOutputStream(file);

    */

    outStream.write(content.getBytes());

    outStream.close();

    }

    }

    展开全文
  • 今天主要说的是把图片保存到本地相册, 一、主要思路: 将一张图片,无论是本地图片还是网络图片先转成Bitmap格式,再调用方法保存到相册中 二、开发过程中可能会遇到的问题: 1:保存成功了,但图库不显示 ...
  • 最近在做项目的时候,遇到了将网络图片资源保存到本地的需求,刚开始是直接开一个下载的线程去下载这张图片,但是考虑到项目图片加载使用的是Universal-image-loader这个第三方的开源库,后来就直接保存bitmap为图片...
  • String getSaveImageFilePath() {File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), YOUR_FOLDER_NAME);// Create a storage directory if it does...
  •  └── R.java ├── ic_launcher-web.png ├── libs │ ├── android-support-v4.jar │ └── gson-2.3.1.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-...
  • if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {//重要的看这里,这是Android 10以上的 values.put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera"); } else { //这是以下的 values.put(MediaStore...
  • android保存yuv数据

    2021-01-26 14:43:28
    播放器解码等功能 的具体实现是在Native层的libplayer.SO动态库中,该lib— 都是YUV数据,但是Android中现在不支持直接渲染 YUV数据,必须把YUV数据转换成Android支持的......package ... import android.graphics.Image...
  • 复制代码 代码如下:/** 保存方法 */public void saveBitmap() {Log.e(TAG, "保存图片");File f = new File("/sdcard/namecard/", picName);if (f.exists()) {f.delete();}try {FileOutputStream out = new ...
  • import android.util.Log;/*将调试信息保存到sdcard上*/public class DebugMessage{public static void put(String s,String name){try{FileOutputStream outStream = new FileOutputStream("/sdcard...
  • android保存文件到手机

    2021-03-23 14:22:36
    手机中的文件保存在对应的目录 /data/data/包名/文件名具体的实现实例package com.example.shoujicunwenjian822.server;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream...
  • 安卓保存图片到本地

    2021-01-09 11:44:40
    private void copyFileByUri(Uri uri) { //存入PICTURES文件夹 String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath(); String filename = ...
  • Android保存文件到本地路径问题常见路径例如: application包名: com.my.company项目名: chat/data/data == ///data/user/0getExternalFilesDir()方法可以获取到 SDCard/Android/data/你的应用的包名/files/ 目录,...
  • 照片: MediaStore.Images.Media.insertImage(getContentResolver(),bmp,fileName, null); bmp.recycle(); bmp = null; ... if (Build.VERSION.SDK_INT >... //这里用handler发送延时消息的方式来扫描而不是直接在...
  • 参考文章: 1....Android通过SharedPreferences API存储和检索键值对。 本文从三个方面讲解SharedPreferences 的使用。 获取共享偏好设置的句柄 写入共享偏好设置 从共享偏好设置...
  • 在业务开发中经常会遇到需要保存对象到文件的需求,如下函数是保存ArrayList<HashMap<String, String>>对象到磁盘,并从磁盘读取还原ArrayList<HashMap<String, String>>对象的方法: /**...
  • import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.net...
  • 1.先创建一个工具类SaveImageUtils public class SaveImageUtils { public static void ... // 首先保存图片 File appDir = new File(Environment.getExternalStorageDirectory(), "Boohee"); if (!appDir.exi
  • import android.content.Context; public class Utils1 { public static boolean saveUserInfo(Context context, String number, String password) { File file = new File(context.getCacheDir(), "it.txt"); try ...
  • 在做项目时,有时会有这样的需求,需要将用户保存的图片和视频文件,能及时在相册中展示和查看,此时如果没有通知相册更新,就不会及时查看到相册中保存的这种图片。那么我们的应用程序如何通知相册刷新并且用户可以...
  • import java.io.File; import java.io.FileNotFoundException;... } 注意文件路径是否存在,不存在就创建 流程:Unity截屏--调用安卓拷贝到相册--扫描保存的文件 解决的问题:截屏图片在相册不显示。
  • } 保存并插入图库 /** * 保存图片到本地图库 并通知刷新图库 * * @param context * @param bmp */ public static void saveImageToGallery(Context context, Bitmap bmp) { // 首先保存图片路径 String ...
  • 项目中有一个需求,从接口获取用户的权限信息。所有的权限信息是这样的:"authorities": ["1003","1002","1001"]每个数字代表一个权限,有权限就返回相应的数字,没有权限就不返回。如果是一个权限还好处理,在多个...
  • 我想用代码中的按钮从URL保存图像,我已经创建了目标文件夹,但是我尝试了各种代码来保存图片,但是什么也不做:public class B_X extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {//...
  • 使用这种方法,它的工作原理void savefile(URI sourceuri){String sourceFilename= ...String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath()+File.separatorChar+"abc...
  • Android开发保存QQ密码

    2021-01-26 14:49:28
    Android开发保存QQ密码 技术要点: 使用文件储存的方式保存数据 实现步骤 ①用户交互界面的设计与实现 ②工具类(FileSaveQQjava )的设计与实现 ③界面逻辑代码的设计与实现
  • 目的:我保存一张图片,然后希望打开系统相册可以看到这张图片。 //代码如下 1.找到这张图片 String filePath = "DCIM/铝达达/1628167429314_share.jpg";//路径替换成自己的 String fileName = "a.jpg";//图片...
  • package ...import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.os.Bundle;import android.os.Environment;impo...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 416,617
精华内容 166,646
关键字:

安卓保存