精华内容
下载资源
问答
  • Android App更新安装APK

    2021-05-28 10:17:35
    原标题:Android App更新安装APK概要一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:检测是否有新版本下载新版本app apk文件安装新的apk通常我们将...

    原标题:Android App更新安装APK

    概要

    一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:

    检测是否有新版本

    下载新版本app apk文件

    安装新的apk

    通常我们将apk文件存放在外部存储上.然后将 文件路径传递给系统, 进行apk的安装.

    文件路径传递过程

    安装代码如下:

    Intent intent = newIntent(Intent.ACTION_VIEW);

    intent.setDataAndType(Uri.fromFile(newApk), "application/vnd.android.package-archive");

    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    startActivity(intent);

    通常情况下这样没问题, 但是在Android7.0 系统上会出现异常FileUriExposedException, 这是因为在7.0 系统上发生的权限变更:

    系统权限更改

    为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问 (0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。此权限更改有多重副作用:

    私有文件的文件权限不应再由所有者放宽,为使用 MODE_WORLD_READABLE 和/或 MODE_WORLD_WRITEABLE 而进行的此类尝试将触发 SecurityException。

    注:迄今为止,这种限制尚不能完全执行。应用仍可能使用原生 API 或 File API 来修改它们的私有目录权限。但是,我们强烈反对放宽私有目录的权限。

    传递软件包网域外的 file:// URI 可能给接收器留下无法访问的路径。因此,尝试传递 file:// URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用 FileProvider。

    DownloadManager 不再按文件名分享私人存储的文件。旧版应用在访问 COLUMN_LOCAL_FILENAME 时可能出现无法访问的路径。面向 Android 7.0 或更高版本的应用在尝试访问 COLUMN_LOCAL_FILENAME 时会触发 SecurityException。通过使用 DownloadManager.Request.setDestinationInExternalFilesDir() 或 DownloadManager.Request.setDestinationInExternalPublicDir() 将下载位置设置为公共位置的旧版应用仍可以访问 COLUMN_LOCAL_FILENAME 中的路径,但是我们强烈反对使用这种方法。对于由 DownloadManager 公开的文件,首选的访问方式是使用ContentResolver.openFileDeor()。

    上述说明在7.0 系统上使用新的 API 来进行文件传递.

    Android 7.0 的文件传递

    官方推荐使用 FileProvider, 那我们看看如何使用

    1. 在 Manifest 文件添加 provider, 如下:

    ...

    ...

    android:name="android.support.v4.content.FileProvider"

    android:authorities="${applicationId}.fileprovider"

    android:exported="false"

    android:grantUriPermissions="true">

    android:name="android.support.FILE_PROVIDER_PATHS"

    android:resource="@xml/provider_paths"/>

    ...

    添加 provider

    2. 设置文件路径

    在 res/ 目录下创建 xml 文件夹, 然后穿件文件 provider_paths.xml, 其内容格式如下:

    指定的路径有6中,其中:

    代表你的app内部存储区域 files/ 目录下的文件, 等同于 Context.getFilesDir().

    代表你的app内部存储区域 files/ 目录下的文件, 等同于 Context.getCacheDir().

    代表外部存储根目录下的文件路径, 等同于 Environment.getExternalStorageDirectory().

    代表你的app外部存储区域根木目录下的路径, 等同于Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)

    代表你的app外部存储区域缓存目录下的路径, 等同于 Context.getExternalCacheDir()

    代表你的app外部存储区域媒体目录下的路径, 等同于Context.getExternalMediaDirs()

    根据自己的需要,设置路径.

    3. 代码中使用FileProvider UricontentUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", newApk);

    这样可以将 Uri 进行传递.

    安装过程

    一般我们直接将apk路径传递给系统进行安装, 如上面的代码:

    Intent intent = newIntent(Intent.ACTION_VIEW);

    intent.setDataAndType(Uri.fromFile(newApk), "application/vnd.android.package-archive");

    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    startActivity(intent);

    但是在 Android8.0 又有权限变更, 需要单独的安装权限:

    所以当在 8.0及以上的系统安装apk是还需添加此权限到 Manifest 文件, 并做判断.

    privatevoidcheckInstallApkPermission(String filePath){

    L.i(TAG, "checkInstallApkPermission:"+ filePath);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

    if(getPackageManager().canRequestPackageInstalls()) {

    L.i(TAG, "can request package");

    launchUpgrade( newFile(filePath));

    } else{

    L.i(TAG, "can not request package");

    launchUpgrade( newFile(filePath));

    }

    } else{

    launchUpgrade( newFile(filePath));

    }

    }

    可能会有人疑惑, 这里为什么if else 都是直接 启动升级安装?

    因为目前国内的定制系统会已经添加授权弹窗, 如果你采用网络所说的直接跳到 Setting界面, 让用户手动选择是比较麻烦的, 如果直接调用安装, 则系统会弹窗提示.

    原创文章, 转载请说明出处~返回搜狐,查看更多

    责任编辑:

    展开全文
  • 还要再Manifast中增加Provider,在res目录下创建xml目录,在xml目录下创建file_path.xml文件文件下载后跳转安装Manifast配置file_path.xmlpublic class UpdateTaskextends AsyncTask{private Contextcontext;...

    7.0以上版本要注意:添加以下代码。还要再Manifast中增加Provider,在res目录下创建xml目录,在xml目录下创建file_path.xml文件

    5f949d29a90b

    文件下载后跳转安装

    5f949d29a90b

    Manifast配置

    5f949d29a90b

    file_path.xml

    public class UpdateTaskextends AsyncTask {

    private Contextcontext;

    private ProgressDialogpd; //进度条对话框

    public UpdateTask(Context context) {

    this.context = context;

    }

    @Override

    protected void onPreExecute() {

    pd =new ProgressDialog(context);

    pd.setCanceledOnTouchOutside(false);

    pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

    pd.setMessage("正在下载更新");

    pd.setProgressNumberFormat("%1d kb/%2d kb");//进度和总数

    pd.setCancelable(false);

    pd.show();

    super.onPreExecute();

    }

    @Override

    protected FiledoInBackground(String... params) {

    String path = params[0];

    String verNew = params[1];

    HttpURLConnection conn =null;

    File file =null;

    //如果相等的话表示当前的sdcard挂载在手机上并且是可用的

    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

    URL url =null;

    try {

    url =new URL(path);

    }catch (MalformedURLException e) {

    e.printStackTrace();

    }

    try {

    if (url.getProtocol().toLowerCase().equals("https")) {

    HttpsURLConnection https = (HttpsURLConnection) url.openConnection();

    https.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    conn = https;

    }else {

    conn = (HttpURLConnection) url.openConnection();

    }

    conn.setConnectTimeout(10000);

    //获取到文件的大小

    int count = conn.getContentLength();

    InputStream is = conn.getInputStream();

    file =new File(Environment.getExternalStorageDirectory(), "nodepp." + verNew +".apk");//下载到本地的app名

    FileOutputStream fos =new FileOutputStream(file);

    BufferedInputStream bis =new BufferedInputStream(is);

    byte[] buffer =new byte[1024];

    int len;

    int total =0;

    while ((len = bis.read(buffer)) != -1) {

    fos.write(buffer, 0, len);

    total += len;

    //获取当前下载量

    publishProgress(total, count);

    }

    fos.close();

    bis.close();

    is.close();

    return file;

    }catch (Exception e) {

    e.printStackTrace();

    }finally {

    }

    }else {

    return null;

    }

    return file;

    }

    @Override

    protected void onProgressUpdate(Integer... values) {

    pd.setProgress(values[0] /1024);

    pd.setMax(values[1] /1024);

    super.onProgressUpdate(values);

    }

    @Override

    protected void onPostExecute(File file) {

    if (file !=null) {

    //安装apk

    Intent intent =new Intent();

    //执行动作

    intent.setAction(Intent.ACTION_VIEW);

    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    if(Build.VERSION.SDK_INT>=24) {//判读版本是否在7.0以上

    //7.0以上需要通过FileProvider获取uri

    Uri apkUri = FileProvider.getUriForFile(context, "com.nodepp.smartnode.fileprovider", file);

    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件

    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");

    }else {

    //执行的数据类型,此处Android应为android,否则造成安装不了

    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");

    }

    context.startActivity(intent);

    pd.dismiss();

    ((Activity)context).finish();

    }else {

    pd.dismiss();

    // 下载app失败

    AlertDialog dialog =new AlertDialog.Builder(context).setTitle("提示")

    .setMessage("应用下载失败")

    .setCancelable(false)

    .setPositiveButton("确定",

    new DialogInterface.OnClickListener() {

    public void onClick(DialogInterface dialog,

    int which) {

    dialog.dismiss();

    }

    }).create();

    dialog.show();

    }

    }

    }

    展开全文
  • Android app的变化可以通过广播监听。广播监听方式分为两种(kotlin) 方式一:动态注册广播服务registerReceiver //action 表示监听动作,如果是有序广播则需要设置priority 优先级 var filter = IntentFilter() //...

    Android app的变化可以通过广播监听。广播监听方式分为两种(kotlin)

    广播的action可以使用系统定义的,也可以使用自定义的,只需要保证监听的action统一即可

    方式一:动态注册广播服务registerReceiver

    //action 表示监听动作,如果是有序广播则需要设置priority 优先级
    var filter = IntentFilter()
    //filter.priority = 100
    filter.addAction("com.unity3d.testkotlin.MyBroadcastRecver")
    //filter.addDataScheme("package")
    registerReceiver(MyBroadcastRecver(),filter)
    

    方式二:静态注册,app安装即可监听

    <receiver android:name=".MyBroadcastRecver"
    	android:exported="true"
    	android:enabled="true" >
    
        <intent-filter>
        	<action android:name="com.unity3d.testkotlin.MyBroadcastRecver" />
        </intent-filter>
    </receiver>
    

    消息监听处理器

    class MyBroadcastRecver:BroadcastReceiver(){
        override fun onReceive(context: Context?, intent: Intent?) {
            //TODO("Not yet implemented")
            if(intent != null){
                //var packagename = intent.dataString
                //dataString的格式是package:xxxx,真正的包名为intent.data.schemeSpecificPart
                var uriData = intent.data
                Toast.makeText(context, intent.action +intent.dataString , Toast.LENGTH_SHORT).show()
                Log.i("Demo","MyBroadcastRecver,action:${intent.action},${uriData!!.schemeSpecificPart}")
            }
        }
    }
    

    所以如果我们需要监听app变化则可以通过监听action事件

    //动态方式
    //必须增加DataScheme,否则接收不到消息
    filter.addAction(Intent.ACTION_PACKAGE_CHANGED)
    filter.addAction(Intent.ACTION_PACKAGE_REMOVED)
    filter.addAction(Intent.ACTION_PACKAGE_ADDED)
    filter.addDataScheme("package")
    
    //静态方式
    //必须增加android:scheme="package",否则接收不到消息
    <intent-filter>
        <action android:name="android.intent.action.PACKAGE_ADDED" />
        <action android:name="android.intent.action.PACKAGE_CHANGED" />
        <action android:name="android.intent.action.PACKAGE_REMOVED" />
    	<data android:scheme="package" />
    </intent-filter>
    

    安装app不运行,此时卸载某app,则可以收到如下通知
    在这里插入图片描述

    展开全文
  • 刚刚开始学习 android studio,遇到两个问题:1, 想用 VM 但是它提示 VT-x 没有打开。 我在 BIOS 模式里 enable VT,但是软件还是提示 VT ...请问为什么 android studio 感觉到我的 VT 打开了?2,我尝试连接手机...

    刚刚开始学习 android studio,遇到两个问题:

    1, 想用 VM 但是它提示 VT-x 没有打开。 我在 BIOS 模式里 enable VT,但是软件还是提示 VT 没有打开。笔记本是SONY,换了 SSD (这没有影响吧?)。我来回重启电脑,也在 BIOS 里检查了好几遍,确定 VT 真的打开了。

    请问为什么 android studio 感觉不到我的 VT 打开了?

    2,我尝试连接手机。用的是 Smartisan T2, android 5.1。手机的 USB 调试模式打开了。我每次点 RUN,手机都会显示:是否安装?我点同意安装。

    4404c1ea4f893d89526181a7b447f6de.png

    然后 android studio 就出现了这一条:

    a10e2234e0d2aab8861bf9d2666927a3.png

    我就点了 OK。

    但是下一次安装还是这样。

    我明明是第一次安装这个 app 啊!而且我每次试验的时候,都给 project 起了不同的名字。我去手机里找,也没有找到同名的安装包,怎么会这样啊?

    请大家赐教。

    展开全文
  • 您从Play商店下载的大多数Android应用程序都会出于各种原因而...在移动设备上重复以下几步:在Android更新应用首先,在智能手机上启动Play商店。它由以下图标表示:输入栏的左上方是菜单图标。触摸以调出Play商...
  • 1、检测app是否安装检测app是否安装的方法有很多,以下列举几种。基本都是利用packageManager来完成。a、通过packagemanager获取已经安装的包,然后对比得出是否安装。代码:public boolean isAppInstalled(Context ...
  • 文章转自...自从API 8后也就是Android2.2后,我们能使APK安装到外部存储上。这是一个可选的特性,在工程的manifest文件中可以进行配置: xmlns:android="http://schemas....
  • Android app 安装目录知识

    千次阅读 2021-06-02 17:36:52
    我们都知道android app有两个安装路径,一个是system/app目录,这个就是所谓的系统应用,只有获得root权限才能删除这个目录下的应用,另一个是data/app目录,用户安装的应用都在这个目录下。几个认知(1)同一个包名的...
  • 硬件损耗问题就讨论了,电子设备都有这个...先来列几个最常见的 安卓app功能:静默下载(未经使用者同意,就先把 apk 包下载下来了)静默升级后台监控应用相互唤醒动动就乱发广播(应用设计不良导致)先列上常见的...
  • 最近在折腾手机app,遇到一个事,华为P40pro手机连接电脑进行app调试的时候,显示安装成功,但是无法打开: 而且手机上也看到app图标,也无法卸载,其实就是没安装上。 android studio里面显示: 11/20 21:38:...
  • 使用Mac电脑进行apk包的安装,将apk包安装手机 前提是需要配置好adb环境 配置好adb环境后执行以下步骤 1.打开终端 2.首先检查手机设备是否连接 adb devices 如果显示 手机识别号 device #表示识别成功 手机识别号 ...
  • ---恢复内容开始---两个app,第一个安装后,再安装第二个,会提示安装包损坏或者一切其他问题,但是这个安装包在别的手机可以正常安装,可以是因为以下问题两个app中,包含有相同名称的providerandroid:name="aaaa...
  • 现在一般的android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新。该小程序实现的就是这个功能。该小程序的特点是,当有更新时,会弹出一个提示框,点击确定,则在...
  • 废话多说 直接上代码,好用你砍我 public void getAppProcessName(Context context) { //当前应用pid final PackageManager packageManager = context.getPackageManager(); final Intent mainIntent = ...
  • 【中关村在线新闻资讯】8月28日消息,Android用户在安装未知来源应用时都会受到来自谷歌的安全警告,但是用户可在设置中开启“允许未知来源”选项,忽略次警告。现在谷歌Android8.0上已经做出了策略调整。Android8.0...
  • 如果光盘自动运行,将会出现如下窗口,如图 4 开始安装所示。点击“取消”按钮,退出 " 系列安装程序” 的安装向导。2. 插上打印机的电源线,打开打印机电源并装好墨盒,打印机一切准备就绪。 3. 然后, 插上 USB 连接线 ,...
  • #Android开发杂记--如何让App自动更新并跳转至安装界面(完美兼容Android10)引言自动更新App的步骤定义FileProviderFileProvider常见问题解析: 引言        一款发行的app不...
  • 在定制化开发中,客户需求要实现对某些app应用限制也就是app安装黑名单功能,在黑名单之中的应用会被限制安装,PMS就是负责管理app安装和卸载的,所以接下来看下PackManagerService.java的源码 @GuardedBy(...
  • 因此,如果单个app的内存占用越小,手机上可以安装运行的app就越多;或者说app的内存占用越小,在手机上运行就会越流畅。所以说,内存占用的大小,也是考量app性能的一个重要指标。2.原理说明对于一个app,我们可以...
  • Android App自动更新基本上是每个App都需具备的功能,参考网上各种资料,自己整理了下,先来看看大致的界面: 一、实现思路: 1.发布Android App时,都会生成output-metadata.json文件和对应的apk文件。(...
  • 手机安卓自带软件可以覆盖安装吗1、可能手机里面,软件残留的东西太多了,建议先...安卓系统手机下软件,但是安装不上,怎么回事?怎么解决?手机无法安装应用解决方法:1,储存模式连接电脑或者用Root Explorer找到SD...
  • 1、默认开启app全部权限Android6.0之后推出动态申请权限,所有敏感权限默认都是没有开启的状态,这两天偶然间看到其他app安装后所有权限(包括敏感权限)默认都是开启的状态,6.0之后敏感权限都需要申请的,怎么可能...
  • 在做android app升级更新时遇到几个问题,我用的测试机是华为V10 系统为8.0一、安装闪退(无反应)解决办法:只要在Mainfest.xml 中加入权限编码即可解决来源参考:...setFlags与addFlags位置顺序不对导致,应该先se...
  • 手机安卓自带软件可以覆盖安装吗1、可能手机里面,软件残留的东西太多了,建议先...安卓系统手机下软件,但是安装不上,怎么回事?怎么解决?手机无法安装应用解决方法:1,储存模式连接电脑或者用Root Explorer找到SD...
  • 原理用一个旧的Apk安装与一个新的Apk安装包使用 bsdiff工具 ,执行命令生成一个差异文件,此差异文件就是我们修改需要更新下载的那部分。引入代码及so文件首先,根据你的系统的架构选择不同的so文件放到你的工程中...
  • 定制Android8.1系统去掉https的抓包限制,编译系统源码时由于oneplus内核的out目录引起报错,先删掉oneplus内核的out目录,如图所示: 分析oneplus的内核源码结构 ...
  • 出现的情况是通过usb可以安装,然后用androidStudio运行生成的apk,发送出去,下载安装,提示未安装应用: 问题如图: 解决过程:在百度上看一些方案,一致呢,问了问别人,通过正确的打包方式打包试一下,尝试过在...
  • 如果你也是个手机软件狂人,喜欢尝试各种各样新奇有趣的软件,面对越来越少的手机内存空间,不得对已经安装的软件痛下**。你是否还在安装与卸载之间纠结?Follow Me!我们一起来给Android系统扩扩容,让“机器人”也...
  • 一、有时候安装一个app想在桌面上显示图标,而是在其他地方调出这个程序。要想在桌面显示图标,只需注释掉APP入口Activity中的<category android:name="android.intent.category.LAUNCHER" />即可,或者...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 319,027
精华内容 127,610
关键字:

安卓手机app更新安装不了