仅在WiFi上下载后台中的大文件

时间:2013-12-21 13:51:18

标签: java android download android-service android-wifi

所以我想要实现的是创建一个将大(~200 MB)文件下载到应用程序内部目录的服务。它应该在取消后恢复(不重启)并在系统重启后自动恢复。它有时应该(如在propeties文件中所写)仅使用WiFi连接下载。

为此,我创建了IntentService(这是一个合适的解决方案吗?),它由Frgament的UI或BroadcastReceiver启动(启动后):

@Override
     public void onHandleIntent(final Intent intent) {
            c.registerReceiver(receiver, new IntentFilter(
                            ConnectivityManager.CONNECTIVITY_ACTION));
            c.registerReceiver(receiver, new IntentFilter(
                            WifiManager.NETWORK_STATE_CHANGED_ACTION));
            receiver.onReceive(null, null); // To start the download the first time
}

最后一行调用处理下载过程的BroadcastReceiver。这是我尝试确保一次只有一个正在下载的方式:

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        boolean allowed = isConnectionAllowed();

        if (allowed && !thread.isAlive()) {

            thread.start();

        } else if (allowed && thread.isAlive()) {

            thread.notify(); // Can this cause any problems in this  case?

        } else if (!allowed && thread.isAlive()) {

            try {

                thread.wait();

            } catch (InterruptedException e) {
                if (StartActivity.DEV_MODE)
                    Log.i(StartActivity.LOG_TAG, Log.getStackTraceString(e));
            }
        }
    }
};

下载itselv分开运行Thread

private Thread thread = new Thread() {
    @SuppressWarnings("resource")
    @Override
    public void run() {

        HttpURLConnection connection = null;
        BufferedInputStream input = null;
        RandomAccessFile output = null;

        try {

            long already_downloaded = 0;

            URL url = new URL(getSource());
            File outputFileCache = new File(getDestination());
            connection = (HttpURLConnection) url.openConnection();

            if (outputFileCache.exists()) {
                connection.setAllowUserInteraction(true);
                connection.setRequestProperty("Range", "bytes="
                        + outputFileCache.length() + "-");
            }

            connection.setConnectTimeout(14000);
            connection.setReadTimeout(20000);
            connection.connect();

            if (connection.getResponseCode() / 100 != 2)
                throw new Exception("Invalid response code!");

            else {
                String connectionField = connection
                        .getHeaderField("content-range");

                if (connectionField != null) {
                    String[] connectionRanges = connectionField.substring(
                            "bytes=".length()).split("-");
                    already_downloaded = Long.valueOf(connectionRanges[0]);
                }

                if (connectionField == null && outputFileCache.exists())
                    outputFileCache.delete();

                long fileLength = connection.getContentLength()
                        + already_downloaded;
                input = new BufferedInputStream(connection.getInputStream());
                output = new RandomAccessFile(outputFileCache, "rw");
                output.seek(already_downloaded);

                byte data[] = new byte[1024];
                int count = 0;
                int progress = 0;
                int progress_last_value = 0;

                while ((count = input.read(data, 0, 1024)) != -1
                        && progress != 100) {
                    already_downloaded += count;
                    output.write(data, 0, count);

                    progress = (int) ((already_downloaded * 100) / fileLength);
                    if (progress != progress_last_value) {
                                // Update notification
                    }
                }
            }

        } catch (MalformedURLException e) {
            if (StartActivity.DEV_MODE)
                Log.i(StartActivity.LOG_TAG, Log.getStackTraceString(e));
        } catch (IOException e) {
            if (StartActivity.DEV_MODE)
                Log.i(StartActivity.LOG_TAG, Log.getStackTraceString(e));
        } catch (Exception e) {
            if (StartActivity.DEV_MODE)
                Log.i(StartActivity.LOG_TAG, Log.getStackTraceString(e));

        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
                if (connection != null)
                    connection.disconnect();
            } catch (IOException e) {
                if (StartActivity.DEV_MODE)
                    Log.i(StartActivity.LOG_TAG, Log.getStackTraceString(e));
            }
        }

        // notify the Fragment using a `LocalBroadcast`.
    }
};

为了确保WiFi连接保持活动,我使用WifiLock类。

注意:我在一些情况下缩短了代码,但我已经设法编写了该代码。

所以我不确定这是否是解决我问题的好方法:

  • 我应该使用IntentService还是普通Service
  • 该解决方案是否使用Thread一个好的解决方案并且有效吗?
    • HttpURLConnection不会过期吗?
    • 我可以这样访问Thread吗? (参考wait()notify()

我知道这是很多代码,但它是我能得到的最接近的代码。我希望有人知道一个解决方案,因为我在这个主题上找不到任何有用的东西(“只在WiFi上打开”,使用谷歌和StackOverflow。)

提前致谢, 菲利克斯

(评论是否需要整个Class

0 个答案:

没有答案