[英]Android API 26 (Oreo) downloading data files from the Internet
I have now resolved this problem, which turned out to be something completely different. 我现在已经解决了这个问题,事实证明这完全不同。 Since no-one has responded, the question can be deleted.
由于没有人回答,因此可以删除该问题。
To support API 26 onward, using Android Studio I have already updated my app to explicitly ask for the dangerous permissions I need (WRITE_EXTERNAL_STORAGE, ACCESS_FINE_LOCATION). 为了支持API 26及更高版本,我已经使用Android Studio更新了应用程序,以明确询问我需要的危险权限(WRITE_EXTERNAL_STORAGE,ACCESS_FINE_LOCATION)。 It also uses normal permission INTERNET, which is granted without needing to ask the user.
它还使用普通权限INTERNET,无需询问用户即可授予该权限。
The app when first run attempts to download to local storage some data files (all text) from a specific web site that hosts these files. 该应用程序在首次运行时会尝试从承载这些文件的特定网站上将一些数据文件(所有文本)下载到本地存储中。 Although it works fine in the API 27 emulator, it fails when tested on my phone running Android 8.1.0 (Huawei P20).
尽管它在API 27模拟器中可以正常工作,但是在运行Android 8.1.0(Huawei P20)的手机上进行测试时,它失败了。
Two files are successfully downloaded, but on the third file it throws an IO exception "premature end of file" when getInputStream is called on the connection, there is a 0 byte transfer, and the app exits after displaying a failure message. 成功下载了两个文件,但是在第三个文件上,当在连接上调用getInputStream时,它会引发IO异常“文件的结尾过早”,传输0字节,并且该应用程序在显示失败消息后退出。 However, if I then Clear Data in the app's settings (on the phone), and restart the app on the phone, the full download of all files is successful.
但是,如果我随后在手机的应用程序设置中清除数据,然后在手机上重新启动应用程序,则所有文件的完整下载成功。
This is the function that is called to download each file (the else clause is what's relevant): 这是调用下载每个文件的功能(else子句是相关的):
// Download file from the internet
public static boolean downloadFile(String urlString, String fileName)
{
mDownloadStatus = false;
// In local file mode, download.tmp must have been pre-loaded
if (LOCAL_FILE_MODE && fileName.equals(LOCAL_FILE_NAME))
{
File f = new File(dataDir, LOCAL_FILE_NAME);
if (f.exists())
mDownloadStatus = true;
else
mErrorString = "Pre-loaded " + LOCAL_FILE_NAME + " not found";
}
else
{
CountDownLatch latch = new CountDownLatch(1);
Runnable r = new DownloadFile(urlString, fileName, latch);
new Thread(r).start();
try
{
// Wait for completion
latch.await();
}
catch (InterruptedException e) {}
}
return mDownloadStatus;
}
And this is the DownloadFile class: 这是DownloadFile类:
public class DownloadFile implements Runnable
{
private String mUrlString;
private String mFileName;
private CountDownLatch mLatch;
public DownloadFile(String urlString, String fileName, CountDownLatch latch)
{
mUrlString = urlString;
mFileName = fileName;
mLatch = latch;
}
public void run()
{
HttpURLConnection urlConnection = null;
Spine.mDownloadStatus = false;
try
{
// set the download URL, a url that points to a file on the internet
// this is the file to be downloaded
URL url = new URL(mUrlString);
// create the new connection
urlConnection = (HttpURLConnection) url.openConnection();
// set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.setUseCaches(false);
// and connect!
urlConnection.connect();
// create a new file, specifying the path, and the filename
// which we want to save the file as.
File file = new File(Spine.dataDir, mFileName);
// this will be used to write the downloaded data into the file we
// created
FileOutputStream fileOutput = new FileOutputStream(file);
// this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
// create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; // used to store a temporary size of the buffer
// now, read through the input buffer and write the contents to the
// file
while ((bufferLength = inputStream.read(buffer)) > 0)
{
// add the data in the buffer to the file in the file output
// stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
}
// close the output stream when done
fileOutput.close();
Spine.mDownloadStatus = true;
}
// catch some possible errors...
catch (IOException e)
{
Spine.mErrorString = e.getMessage();
}
if (urlConnection != null)
urlConnection.disconnect();
// Signal completion
mLatch.countDown();
}
}
What do I need to do to fix this? 我需要做什么来解决这个问题? I am at my wit's end!
我没办法!
After changing the code to more properly deal with asking for permissions, the original problem described no longer existed. 更改代码以更正确地处理请求权限后,描述的原始问题不再存在。 However I had a totally different problem which I solved.
但是,我有一个完全不同的问题可以解决。 Outline of problem: Worked with API27 emulator in both debug and release builds.
问题概述:在调试和发行版本中都使用API27仿真器。 On Huawei P20 (API27), worked on debug, failed on release.
在华为P20(API27)上进行调试,但发布失败。 Once I discovered I could enable debugging for the release build I was able to find the problem and fix it.
一旦发现,就可以为发布版本启用调试功能,便可以找到问题并进行修复。
SharedPreferences for the application seem to persist on the phone somehow even when the app has been uninstalled. 即使卸载了该应用程序,该应用程序的SharedPreferences仍会以某种方式保留在电话上。 The problem was that SharedPreferences said that certain files had already been downloaded when of course they no longer existed on the phone.
问题在于,SharedPreferences表示某些文件当然已经下载了,当然它们在手机上已经不存在了。 My fix was to check in this case if the file existed, and if not I reset the preferences so that the download took place.
我的解决方法是在这种情况下检查文件是否存在,如果不存在,我将重置首选项,以便进行下载。
(I have a suspicion that it was picking up previous SharedPreferences from an earlier version of the app, installed from the Google Play Store and uninstalled so I could test the new version.) (我怀疑它是从较早版本的应用程序中获取先前的SharedPreferences的,并已从Google Play商店安装并卸载了,以便我可以测试新版本。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.