我想编写一个从url下载.apk文件并将其放入外部存储,然后启动更新的代码。但是我遇到了Kitkat设备的问题(仅在仿真器上进行过测试)。
经过很少的研究,我发现 Kitkat似乎使用okhttp而不是以前的HTTPConnection实现,或者至少在具有官方更新的Nexus设备上就是这种情况。
日志:
W/dalvikvm: VFY: unable to find class referenced in signature (Ljava/nio/file/Path;)
VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;)
I/dalvikvm: Could not find method java.nio.file.Files.newOutputStream, referenced from method okio.Okio.sink
W/dalvikvm: VFY: unable to resolve static method 45672: Ljava/nio/file/Files;.newOutputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/OutputStream;
D/dalvikvm: VFY: replacing opcode 0x71 at 0x000a
W/dalvikvm: VFY: unable to find class referenced in signature (Ljava/nio/file/Path;)
VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;)
I/dalvikvm: Could not find method java.nio.file.Files.newInputStream, referenced from method okio.Okio.source
W/dalvikvm: VFY: unable to resolve static method 45671: Ljava/nio/file/Files;.newInputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/InputStream;
D/dalvikvm: VFY: replacing opcode 0x71 at 0x000a
I/update_statut: onFailure : Connection closed by peer
通过这种方式,我使用Asyntask在后台下载文件并将其过去。
private static Boolean isDownloaded = false ;
private OkHttpClient client;
public class update extends AsyncTask<String,String,String>{
private Context context;
update (Context context){
this.context=context;
}
@Override
protected String doInBackground(String... sUrl) {
String path = Environment.getExternalStorageDirectory() + "/download/" + "myapp.apk";
DownloadFile("https://linktodownload.com/myapp.apk"); // URL example.
return path;
}
@Override
protected void onPostExecute(String path) {
//////////// Install Downloaded Apk
if (isDownloaded) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
File newFile = new File(path);
String ext = newFile.getName().substring(newFile.getName().lastIndexOf(".") + 1);
String type = mime.getMimeTypeFromExtension(ext);
try {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri contentUri = FileProvider.getUriForFile(context, "com.mypackage.fileProvider", newFile);
intent.setDataAndType(contentUri, type);
} else {
intent.setDataAndType(Uri.fromFile(newFile), type);
}
context.startActivity(intent);
} catch (ActivityNotFoundException anfe) {
Log.i("update_statut", "onPostExecute Error : " + anfe.getMessage());
}
}
}
}
public void DownloadFile(String apkurl){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 110);
Log.i("update_statut", "Request Permission WRITE_EXTERNAL_STORAGE , Allow Permissions & Restart App");
isDownloaded= false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 110);
Log.i("update_statut", "Request Permission READ_EXTERNAL_STORAGE, Allow Permissions & Restart App");
isDownloaded = false;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
&&
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
{
Log.i("update_statut", "Granted Permission WRITE AND READ EXTERNAL_STORAGE");
Write_File(apkurl);
}
else if(Build.VERSION.SDK_INT==21 || Build.VERSION.SDK_INT==22)
{
Log.i("update_statut", "Lolipop");
Write_File(apkurl);
}
else if(Build.VERSION.SDK_INT <= 20){
Log.i("update_statut", "KitKat");
/////// PROBLEM IN THIS CODE
client = new OkHttpClient();
Request request = new Request.Builder().url(apkurl).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("update_statut","onFailure : "+e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()){
String PATH = Environment.getExternalStorageDirectory() + "/download/";
File file = new File(PATH);
File outputFile = new File(file, "myapp.apk");
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = response.body().byteStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
isDownloaded = true;
Log.i("update_statut", "file Created");
}
}
});
}
}
public void Write_File(String apkurl){
try {
URL url = new URL(apkurl);
URLConnection connection = url.openConnection();
connection.connect();
String PATH = Environment.getExternalStorageDirectory() + "/download/";
File file = new File(PATH);
if (!file.exists()) {
file.mkdirs();
}
File outputFile = new File(file, "myapp.apk");
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = connection.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
isDownloaded = true;
} catch(IOException e){
Log.i("update_statut", "Download File Error : " + e.getMessage());
isDownloaded = false;
}
}
以下是清单中声明的权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
还调用了清单中的提供程序
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mypackage.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Build.gradle实现
implementation 'com.squareup.okhttp3:okhttp:3.9.1'