Java 我需要下载几个图像到目录,以便内容可以脱机访问

Java 我需要下载几个图像到目录,以便内容可以脱机访问,java,android,json,caching,android-glide,Java,Android,Json,Caching,Android Glide,我得到一些JSON数据,其中包含一些食物菜单项 请注意:这只是一个示例,数组中有时有2个以上的图像和更多的菜单项 { "menu": [ { "url": "/api/v1/menu/1", "name": "Best Food", "description": "really nice food", "opening_time": "every day from 9am to 6pm", "contact_email":

我得到一些JSON数据,其中包含一些食物菜单项

请注意:这只是一个示例,数组中有时有2个以上的图像和更多的菜单项

{
  "menu": [
    {
      "url": "/api/v1/menu/1",
      "name": "Best Food",
      "description": "really nice food",
      "opening_time": "every day from 9am to 6pm",
      "contact_email": "info@food.com",
      "tel_number": "+54 911 3429 5762",
      "website": "http://bestfood.com",
      "images": [
        {
          "url": "https://blahblah/image1.jpg"
        },
        {
          "url": "https://blahblah/image2.jpg"
        }
      ]
    },

  ]
}
每个项目都有一些信息和图像URL数组

我正在使用Glide图像库来处理这些图像,并对2.0进行改造,从端点下载JSON数据。在这一点上一切都很好

但是,我需要存储这些下载的数据以供脱机访问

目前,我在现有模型上使用ORMLite将所有JSON数据存储在数据库中。这部分没问题

然而,在我的数据库中,我只存储图像URL,因为我被告知在数据库中存储图像(作为blob)不是一种好方法

因此,我的应用程序中有一个部分可以查看保存的菜单,如果用户选择,可以选择下载以进行脱机访问。

此时值得一提的是,我已经在数据库中拥有了原始菜单信息,因为用户必须首先查看菜单才能在DB中获得它

但问题在于图像

这就是我不知道如何进行的地方,但我列出了我正在思考的解决方案和问题,并希望人们能就最佳行动方案向我提供建议

  • 使用服务下载图像。我觉得这是强制性的,因为我不知道会有多少图像,我希望下载继续进行,即使用户退出应用程序

  • Glide有一个只下载图像的选项,您可以在我读取和删除图像时配置其缓存的位置(内部私有或外部公共)。问题是我对设置缓存大小感到不舒服,因为我不知道需要什么。我想设定无限

  • 我需要能够删除保存的菜单数据,尤其是如果它保存在外部公共目录中,因为在删除应用程序时,不会删除这些数据,等等,或者如果用户选择从应用程序中删除保存的菜单。我想我可以将文件图像URI或整个保存菜单的位置存储在数据库中,但不确定这是否是一种好方法

  • 我在不同的来源和答案中读到,在这个用例中,我只是将图像缓存到SD卡等。我应该特别使用一个网络库来这样做,以避免将位图分配到堆内存。我正在我的应用程序中使用OK HTTP


  • 如果您希望即使用户退出也能继续下载,那么使用服务可能是一个不错的选择。卸载应用程序时,将自动删除存储在使用
    getExternalStorageDirectory()
    创建的目录中的图像。此外,您还可以检查内部内存是否足够大以存储图像。如果您使用此方法,这些图像将在卸载应用程序时删除。

    1:使用IntentService进行下载

    2:使用AlarmManager设置您的IntentService,以便即使 应用程序未运行。您可以向AlarmManager注册

    有多种方法可以让AlarmManager启动您的应用程序 意图

    例如: //注册第一次运行,然后记录重复循环的间隔。 alarmManager.setInexactRepeating(alarmManager.Appeased\u REALTIME\u唤醒, SystemClock.elapsedRealtime()+默认值\u初始运行, 默认运行间隔(pi)

    3:存储数据 这里有几个选项,这取决于您想要的公共服务的公开程度 图片/数据将被删除

    示例:外部公共存储 文件dirBackup=Environment.getExternalStoragePublicDirectory( “你的目录”)

    4:下载

    你的选择在这里。您可以使用从当前API到 基本URL连接

    您可能想看看:

    http://developer.android.com/reference/android/app/DownloadManager.html
    
    另外,注意您需要添加的权限 和

    希望这能为您指明一个有用的方向。

    尝试一下这个方法来管理图像加载

    使用服务下载图像。我觉得这是强制性的,因为 我不知道会有多少图像,我想下载 即使用户退出应用程序也要继续

    所有下载都是在工作线程中完成的,所以在应用程序进程处于活动状态时它是活动的。可能会出现一个问题:加载过程中应用程序死亡。为了解决这个问题,我建议将
    AlarmManager
    Service
    结合使用。将其设置为按计时器启动,检查数据库或UIL缓存中是否有未加载的图像文件,然后再次开始加载

    Glide有一个仅用于图像下载的选项,您可以进行配置 其缓存所在的位置(内部私有或外部公共),如 阅读这里和这里。问题是我对这个设置感到不舒服 缓存大小,因为我不知道需要什么。我想订一套 无限的

    UIL有几种现成的磁盘缓存实现,包括无限的一种。它还为您提供缓存接口,以便您可以实现自己的缓存接口

    我需要能够删除保存的菜单数据,尤其是如果 保存在外部公用目录中,因为在 应用程序被删除等,或者如果用户选择从 在应用程序中。我想我可以存储文件映像URI或 数据库中为此保存的整个菜单的位置,但不确定是否 这是一个好办法

    UIL使用提供的文件链接为每个加载的文件生成唯一的文件名。您可以使用JSON中的链接删除任何加载的图像或取消任何下载

    我从不同的来源和答案中了解到,在这个用例中,我只是为了 缓存图像到SD卡等,我应该特别使用 网络库
    ImageLoader imageLoader=new ImageLoader(context);
    imageLoader.DisplayImage(url, imageView);
    
     public FileCache(Context context){
        //Find the dir to save cached images
        ...
            cacheDir=new File(android.os.Environment.getExternalStorageDirectory(),"LazyList");
        ...
    }
    
     /**
     * This method delete a file if exist
     */
    public static void deleteFile(File file){
        if(file!=null && file.exists()) {
            file.delete();
        }
    }
    
      class DownloadFile extends AsyncTask<String,Integer,Long> {
        ProgressDialog mProgressDialog = new ProgressDialog(MainActivity.this);// Change Mainactivity.this with your activity name. 
        String strFolderName;
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            mProgressDialog.setMessage("Downloading Image ...");
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.setMax(100);
            mProgressDialog.setCancelable(false);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.show();
        }
        @Override
        protected Long doInBackground(String... aurl) {
            int count;
            try {
                URL url = new URL((String) aurl[0]);
                URLConnection conexion = url.openConnection();
                conexion.connect();
                String targetFileName="downloadedimage.jpg";//Change name and subname
    
                int lenghtOfFile = conexion.getContentLength();
                String PATH = Environment.getExternalStorageDirectory()+"/myImage/";
                File folder = new File(PATH);
                if(!folder.exists()){
                    folder.mkdir();//If there is no folder it will be created.
                }
                InputStream input = new BufferedInputStream(url.openStream());
                OutputStream output = new FileOutputStream(PATH+targetFileName);
                byte data[] = new byte[1024];
                long total = 0;
                while ((count = input.read(data)) != -1) {
                    total += count;
                           publishProgress ((int)(total*100/lenghtOfFile));
                    output.write(data, 0, count);
                }
                output.flush();
                output.close();
                input.close();
            } catch (Exception e) {}
            return null;
        }
        protected void onProgressUpdate(Integer... progress) {
             mProgressDialog.setProgress(progress[0]);
             if(mProgressDialog.getProgress()==mProgressDialog.getMax()){
                mProgressDialog.dismiss();
    
                Toast.makeText(getApplicationContext(), "Download Completed !", Toast.LENGTH_LONG).show();
    
             }
        }
        protected void onPostExecute(String result) {
        }
    }
    
      new DownloadFile().execute("https://i.stack.imgur.com/w4kCo.jpg");
    
      <uses-permission android:name="android.permission.INTERNET"/>
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    public class ImageLoader {
    
    MemoryCache memoryCache = new MemoryCache();
     FileCache fileCache;
    private Map<ImageView, String> imageViews = Collections
            .synchronizedMap(new WeakHashMap<ImageView, String>());
    ExecutorService executorService;
    // Handler to display images in UI thread
    Handler handler = new Handler();
    
    public ImageLoader(Context context) {
        fileCache = new FileCache(context);
        executorService = Executors.newFixedThreadPool(5);
    }
    
    final int stub_id = R.drawable.placeholder;
    
    public void DisplayImage(String url, ImageView imageView) {
        imageViews.put(imageView, url);
    
    
    
        Bitmap bitmap = memoryCache.get(url);
        if (bitmap != null)
            imageView.setImageBitmap(bitmap);
        else {
            queuePhoto(url, imageView);
            imageView.setImageResource(stub_id);
        }
    }
    
    private void queuePhoto(String url, ImageView imageView) {
        PhotoToLoad p = new PhotoToLoad(url, imageView);
        executorService.submit(new PhotosLoader(p));
    }
    
    private Bitmap getBitmap(String url) {
        File f = fileCache.getFile(url);
    
        Bitmap b = decodeFile(f);
        if (b != null)
            return b;
    
        // Download Images from the Internet
        try {
            Bitmap bitmap = null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imageUrl
                    .openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is = conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            conn.disconnect();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Throwable ex) {
            ex.printStackTrace();
            if (ex instanceof OutOfMemoryError)
                memoryCache.clear();
            return null;
        }
    }
    
    // Decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f) {
        try {
            // Decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            FileInputStream stream1 = new FileInputStream(f);
            BitmapFactory.decodeStream(stream1, null, o);
            stream1.close();
    
            // Find the correct scale value. It should be the power of 2.
            // Recommended Size 512
            final int REQUIRED_SIZE = 70;
            int width_tmp = o.outWidth, height_tmp = o.outHeight;
            int scale = 1;
            while (true) {
                if (width_tmp / 2 < REQUIRED_SIZE
                        || height_tmp / 2 < REQUIRED_SIZE)
                    break;
                width_tmp /= 2;
                height_tmp /= 2;
                scale *= 2;
            }
    
            // Decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize = scale;
            FileInputStream stream2 = new FileInputStream(f);
            Bitmap bitmap = BitmapFactory.decodeStream(stream2, null, o2);
            stream2.close();
            return bitmap;
        } catch (FileNotFoundException e) {
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    // Task for the queue
    private class PhotoToLoad {
        public String url;
        public ImageView imageView;
    
        public PhotoToLoad(String u, ImageView i) {
            url = u;
            imageView = i;
        }
    }
    
    class PhotosLoader implements Runnable {
        PhotoToLoad photoToLoad;
    
        PhotosLoader(PhotoToLoad photoToLoad) {
            this.photoToLoad = photoToLoad;
        }
    
        @Override
        public void run() {
            try {
                if (imageViewReused(photoToLoad))
                    return;
                Bitmap bmp = getBitmap(photoToLoad.url);
                memoryCache.put(photoToLoad.url, bmp);
                if (imageViewReused(photoToLoad))
                    return;
                BitmapDisplayer bd = new BitmapDisplayer(bmp, photoToLoad);
                handler.post(bd);
            } catch (Throwable th) {
                th.printStackTrace();
            }
        }
    }
    
    boolean imageViewReused(PhotoToLoad photoToLoad) {
        String tag = imageViews.get(photoToLoad.imageView);
        if (tag == null || !tag.equals(photoToLoad.url))
            return true;
        return false;
    }
    
    // Used to display bitmap in the UI thread
    class BitmapDisplayer implements Runnable {
        Bitmap bitmap;
        PhotoToLoad photoToLoad;
    
        public BitmapDisplayer(Bitmap b, PhotoToLoad p) {
            bitmap = b;
            photoToLoad = p;
        }
    
        public void run() {
            if (imageViewReused(photoToLoad))
                return;
            if (bitmap != null)
                photoToLoad.imageView.setImageBitmap(bitmap);
            else
                photoToLoad.imageView.setImageResource(stub_id);
        }
    }
    
    public void clearCache() {
        memoryCache.clear();
        fileCache.clear();
    }
    
     ImageLoader Imageloaer = new ImageLoader(getBaseContext());
        Imageloaer.DisplayImage(imageUrl, imageView);