- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要能够通过检查某处托管的 apk 的较新版本(通过 versionCode/versionName)来推送对私有(private)应用程序(Play 商店中不存在)的更新*。
我相信我已经获得了我需要的所有代码 - 连接到 Dropbox,下载文件,触发广播接收器检查版本并安装应用程序(如果有比当前版本更新的版本可用)。
我的问题是 getPackageArchiveInfo 总是在下载的 apk 上返回 null。
注意:我可以在下载应用程序后手动安装它(文件未损坏),但我需要这个过程自动化。
*在此示例中使用 Dropbox,但这不是 prod 使用的。
我使用了一些不同的资源来构建并尝试调试我的问题,请参阅:
Android: install .apk programmatically
Android install apk with Intent.VIEW_ACTION not working with File provider
compileSdkVersion是27,minSdkVersion和targetSdkVersion是23,这个配置很关键,不能改。
我主要在设置为生产设备将使用的特定配置的模拟器上进行测试,但我也使用 Galaxy S6 进行测试。
主要 Activity :
public void onCheckClick(View view) {
try {
String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
txtCurrent.setText("Current: " + versionName);
String url = apkLocation;
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("description");
request.setTitle("app-debug.apk");
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-debug.apk");
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
public void onUpdateClick(View view) {
Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
installIntent.setDataAndType(Uri.parse("file:///storage/emulated/0/Download/app-debug.apk"), "application/vnd.android.package-archive");
startActivity(installIntent);
}
下载广播接收者:
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)){
//do stuff
PackageManager pm = context.getPackageManager();
String apkName = "app-debug.apk";
String fullPath = Environment.DIRECTORY_DOWNLOADS + "/" + apkName;
PackageInfo info = pm.getPackageArchiveInfo(fullPath, 0);
Toast.makeText(context, info.packageName, Toast.LENGTH_LONG).show();
}
}
安卓 list :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".DownloadBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</receiver>
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
</application>
预期:从下载的 apk 中获取版本信息,如果 apk 有更新的版本,则能够安装该 apk。
实际:版本信息为空,无法继续处理。
最佳答案
我遇到了同样的问题。我刚刚解决了它。这是我的解决方案:(注意:我在这里使用了 FTP 服务器,Targated SDK 23)
安卓 list :
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
下载 Apk 类:
class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> {
@Override
protected void onPreExecute() {
super.onPreExecute();
progressdlg = new ProgressDialog(DownloadApk.this);
progressdlg.setCancelable(false);
progressdlg.setMessage("Downloading...");
progressdlg.setProgressStyle(progressdlg.STYLE_SPINNER);
//progressdlg.setMax(100);
progressdlg.setIndeterminate(true);
progressdlg.setCanceledOnTouchOutside(false);
progressdlg.show();
}
@Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
progressdlg.dismiss();
if(result){
Toast.makeText(DownloadApk.this,"Done!!", Toast.LENGTH_SHORT).show();
OpenNewVersion(path);
}else{
Toast.makeText(DownloadApk.this,"Error: Server Connection Failed!", Toast.LENGTH_SHORT).show();
}
}
@Override
protected Boolean doInBackground(String... arg0) {
Boolean flag = false;
String sdcardRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
String apkSavePath = sdcardRoot+"/app-debug.apk";
path=apkSavePath;
try {
String server = "103.121.78.28"; //Your download Link
int port = 21;
String user = "ftp";
String pass = "";
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
String remoteFile1 = "app-debug.apk";//apk name
File downloadFile1 = new File(apkSavePath);
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
Log.d("Update", "doInBackground: "+"before if"+success);
if (success) {
Log.d("Update", "doInBackground: "+"Success"+success);
flag = true;
}
} catch (IOException ex) {
progressdlg.dismiss();
System.out.println("Error: " + ex.getMessage());
flag = false;
ex.printStackTrace();
} finally {
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
progressdlg.dismiss();
}
} catch (IOException ex) {
progressdlg.dismiss();
ex.printStackTrace();
flag = false;
}
}
} catch (Exception e) {
progressdlg.dismiss();
Log.e("TAG", "Update Error: " + e.getMessage());
e.printStackTrace();
flag = false;
}
return flag;
}
}
void OpenNewVersion(String location) {
File apkFile = new File(location);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri uri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext().getPackageName() + ".provider", apkFile);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
}
startActivity(intent);;
}
// Function to check and request permission.
public void checkPermission(String permission, int requestCode)
{
if (ContextCompat.checkSelfPermission(DownloadApk.this, permission)
== PackageManager.PERMISSION_DENIED) {
// Requesting the permission
ActivityCompat.requestPermissions(DownloadApk.this,
new String[] { permission },
requestCode);
}
else {
Toast.makeText(DownloadApk.this,
"Permission already granted",
Toast.LENGTH_SHORT)
.show();
}
}
// This function is called when the user accepts or decline the permission.
// Request Code is used to check which permission called this function.
// This request code is provided when the user is prompt for permission.
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super
.onRequestPermissionsResult(requestCode,
permissions,
grantResults);
if (requestCode == STORAGE_PERMISSION_CODE) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(DownloadApk.this,
"Storage Permission Granted",
Toast.LENGTH_SHORT)
.show();
}
else {
Toast.makeText(DownloadApk.this,
"Storage Permission Denied",
Toast.LENGTH_SHORT)
.show();
}
}
}
从任何点击监听器调用下载 Apk 类:
new DownloadNewVersion ().execute();
关于java - 如何以编程方式下载和安装 apk?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55732011/
当我尝试通过我的 .exe 文件从 url 下载 .pdf 文件时出现以下错误。 The server committed a protocol violation. Section=Response
我是一家非营利组织的 G Suite 管理员,刚刚发现数据导出功能,这似乎是个人帐户的外卖。 导出文件已准备好,现在可以从 Google Cloud Platform Storage 中的存储桶下载。
导航 引言 总体思路 七牛云相关的配置文件 获取七牛云上传token 相关类定义 核心代码实现 获取七牛云图片下载链接 公开空
这不是后端编程问题。我只能修改标记或脚本(或文档本身)。我在这里问的原因是因为我对适当术语的所有搜索都不可避免地导致有关编程此功能的问题和解决方案。我不是试图通过编程来强制它;我必须找出此 PDF 行
您好,我已在 Google AdSense 中注册,我想使用适用于 iOS 的 SDK,但目前我找不到 SDK 下载链接。 我的申请已获批准。 任何人都知道如何下载这个sdk。 我使用这个链接来描述如
我需要为当前在 SourceForge 上的 github 项目提供二进制文件和文档。在那里,我可以为我需要的下载提供一个目录结构,因为我必须为大约 10 个不同的操作系统提供几个版本。 github
我从 Canvas 下载绘图时遇到问题。这是我的代码: function downloadCanvas(link, canvasId, filename) { link.href =
ASP.NET 项目 我将使用 Azure 进行存储。问题(要求): 在我的项目中,我让注册用户下载文件。但我不希望用户将此下载链接分享给未注册的人(例如:我给注册用户的下载链接只能在他们的计算机上下
我编写了一个servlet,用于检查http header ,但我不知道为什么当页面加载时,它会自动开始下载。 /* * To change this template, choose To
我正在尝试将下载添加到我的网络浏览器,但遇到的问题是获取您尝试下载的文件的名称。这是我的下载代码: engine.locationProperty().addListener(new ChangeLi
我正在尝试下载网站的 html: String encoding = "UTF-8"; HttpContext localContext = new BasicHttpContext();
我制作了一个带有“开始下载”按钮的框架,用于从网站下载 JAR。 问题是每当我点击开始下载按钮时,整个框架就会卡住,直到下载完成,然后就正常了。 我该如何解决这个问题? 这是单击按钮时执行的代码 p
我得到这段代码来实现一些东西,它可以帮助我从给定的 URL 下载文件。 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSes
我正在尝试创建一个 Controller 来使用流方法下载和上传文件,在我的例子中,所有文件都作为 Blob 保存在数据库中。我阅读了 Jboss Netty 的文档,但我认为这不是我的最佳解决方案。
下载并保存文件 let destination: DownloadRequest.DownloadFileDestination = { _, _ in // var fileURL = sel
使用 htaccess 我基本上试图禁止访问该页面,即 http://example.com , 但它仍然允许人们下载文件,如果他们有直接链接即 http://example.com/hi.zip .
我正在寻求将脚本与我的控制面板集成,并且由于我是新手脚本编写者而遇到问题。我想做的是用 1 个脚本下载一个文件并解压它。 示例: wget http://example.com/example.tar
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
这个问题在这里已经有了答案: Top techniques to avoid 'data scraping' from a website database (14 个答案) 关闭 5 年前。 我有
这个问题在这里已经有了答案: Reading and parsing email from Gmail using C#, C++ or Python (6 个答案) 关闭 7 年前。 我只是想,是
我是一名优秀的程序员,十分优秀!