实现安卓app自动更新功能实例方案

安卓应用实现自动更新比较简单,这里跟大家介绍下。

1. web接口

需要提供一个接口供客户端查询更新状态,并且在需要更新时,告知客户端新APK地址。

接口参数如下:

    package   包名,因为有时候会出现同一个应用换包名打包的情况
    version 版本号,即android清单文件里面的versionCode
    channel 渠道号
    os 操作系统,android/ios。ios 这里仅作预留。

 

之所以传入这些字段,是要在与服务器端的包匹配时,务必满足:

    package, channel, os 相等,并且服务器端的version 大于 客户端传入的version

代码如下:

os = request.GET.get('os')
pkg_name = request.GET.get('package')
channel = request.GET.get('channel')
version = request.GET.get('version')

if not os or not pkg_name or not channel or not version:
    return jsonify(**ret_dict)
pkg = Package.objects.filter(
    os=os,
    package=pkg_name,
    channel=channel,
    status__gt=config.PACKAGE_STATUS_NOT_UPDATE
).order_by('-version').first()
if pkg and int(version) < pkg.version:
    ret_dict['pkg_status'] = str(pkg.status)
    ret_dict['pkg_url'] = config.WEB_HOST + pkg.file.url
    ret_dict['update_prompt'] = pkg.info
return jsonify(**ret_dict)

2. 数据库设计

由于web端使用的是django,所以可以很方便的给出运营同学可以操作的后台界面,如下:

注意红框内的元素,运营同学在上传时,是不允许修改的,而是由程序自动解析APK文件得到后填入的。

具体的解析方法,我们稍后给出。

而对应的models代码如下:

class Package(models.Model):
    file = models.FileField(u'文件', upload_to=config.PACKAGE_UPLOAD_PATH)
    package = models.CharField(u'包名', max_length=255, blank=True, default='')
    version = models.IntegerField(u"版本号", blank=True, default=0, null=True)
    channel = models.CharField(u"渠道", max_length=128, blank=True, default='')
    status = models.IntegerField(u'更新状态', default=config.PACKAGE_STATUS_NOT_UPDATE,
        choices=config.PACKAGE_UPDATE_STATUS)
    info = models.TextField(u'通知信息', blank=True, null=True)
    os = models.CharField(u'操作系统', max_length=64, default=config.PACKAGE_CLIENT_UNKNOW,
        choices=config.PACKAGE_CLIENT_OS, blank=True, null=True)

    def __unicode__(self):
        _,name = os.path.split(self.file.name)
        return name

    class Meta:
        unique_together = ('package', 'version', 'channel', 'os')

    def save(self, * args, ** kwargs):
        # 文件上传成功后,文件名会加上PACKAGE_UPLOAD_PATH路径
        path,_ = os.path.split(self.file.name)
        if not path:
            if self.file.name.endswith('.apk'):
                self.os = config.PACKAGE_CLIENT_ANDROID
                path = os.path.join('/tmp', uuid.uuid4().hex + self.file.name)
                # logger.error('path: %s', path)
                with open(path, 'wb+') as destination:
                    for chunk in self.file.chunks():
                        destination.write(chunk)
                info = parse_apk_info(path)
                os.remove(path)
                self.package = info.get('package', '')
                self.version = info.get('version', 0)
                self.channel = info.get('channel', '')
            elif self.file.name.endswith('ipa'):
                self.os = config.PACKAGE_CLIENT_IOS

        super(self.__class__, self).save(*args, ** kwargs)

    def display_filename(self):
        _,name = os.path.split(self.file.name)
        return name
    display_filename.short_description = u"文件"

3. APK文件解析

def parse_apk_info(apk_path, tmp_dir='/tmp'):
    """
    获取包名、版本、渠道:
    {'version': '17', 'channel': 'CN_MAIN', 'package': ‘com.fff.xxx'}
    :param apk_path:
    :return:
    """
    from bs4 import BeautifulSoup
    import os
    import shutil
    import uuid

    abs_apk_path = os.path.abspath(apk_path)
    dst_dir = os.path.join(tmp_dir, uuid.uuid4().hex)
    jar_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'apktool.jar'))
    cmd = 'java -jar %s d %s %s' % (jar_path, abs_apk_path, dst_dir)

    if isinstance(cmd, unicode):
        cmd = cmd.encode('utf8')

    # 执行
    os.system(cmd)

    manifest_path = os.path.join(dst_dir, 'AndroidManifest.xml')

    result = dict()

    with open(manifest_path, 'r') as f:
        soup = BeautifulSoup(f.read())
        result.update(
            version=soup.manifest.attrs.get('android:versioncode'),
            package=soup.manifest.attrs.get('package'),
        )

        channel_soup = soup.find('meta-data', attrs={'android:name': 'UMENG_CHANNEL'})
        if channel_soup:
            result['channel'] = channel_soup.attrs['android:value']

    shutil.rmtree(dst_dir)

    return result

当然,正如大家所看到的,我们需要依赖于 apktool.jar 这个文件,具体大家可以在网上下载。

时间: 2024-08-24 22:14:42

实现安卓app自动更新功能实例方案的相关文章

Android应用APP自动更新功能的代码实现_Android

由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

Android应用APP自动更新功能的代码实现

由于Android项目开源所致,市面上出现了N多安卓软件市场.为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量.因此我们有必要给我们的Android应用增加自动更新的功能. 既然实现自动更新,我们首先必须让我们的应用知道是否存在新版本的软件,因此我们可以在自己的网站上放置配置文件,存放软件的版本信息: <update> <version>2</version> <name>baidu

Android如何实现APP自动更新_Android

先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

Android如何实现APP自动更新

先来看看要实现的效果图: 对于安卓用户来说,手机应用市场说满天飞可是一点都不夸张,比如小米,魅族,百度,360,机锋,应用宝等等,当我们想上线一款新版本APP时,先不说渠道打包的麻烦,单纯指上传APP到各大应用市场的工作量就已经很大了,好不容易我们把APP都上传完了,突然发现一个会导致应用闪退的小Bug,这时那个崩溃啊,明明不是很大的改动,难道我们还要再去重新去把各大应用市场的版本再上传更新一次?相信我,运营人员肯定会弄死你的!! 有问题,自然就会有解决问题的方案,因此我们就会想到如果在APP里

Android程序自动更新功能模块的实现方法【附完整demo源码下载】_Android

本文实例讲述了Android程序自动更新功能模块的实现方法.分享给大家供大家参考,具体如下: 在程序启动的时候检测服务器上有没有对应版本更新,如果有更新,提示用户是否更新. 在程序启动的时候首先调用更新模块检测服务器上存放的版本号跟当前程序的版本号如果大于当前版本号,弹出更新对话框,如果用户选择更新,则显示当前更新状态,然后替换当前程序. 程序调用版本更新检测: private UpdateManager updateMan; private ProgressDialog updateProgr

Android App 自动更新版本

概述 其实Android App自动更新这个功能是很重要的,原因就在于Android 是开源的,所以国内出现了很多Android 的应用市场,所以如果你的一个App在一个AppStore里面上线了,然后你又有一个新的版本出来了的话,如果不写自动更新的话就得一个应用市场一个应用市场的发布,是不是感觉心很累,所以自动更新版本,还是很重要的. 服务器数据 当然为了能够让你的App知道是否该更新了,所以得有一个固定的服务器,以便于你得到更新的数据.我设计的包括以下数据(可能有不足的地方,具体情况因人而异

Android应用自动更新功能实现的方法_Android

本文给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应

Android应用自动更新功能的实现!!!

一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应用就保持最新的拉. 为了让大家容易理解,我像往常一样准备一个小

Android应用自动更新功能实现的方法

本文给大家分享Android里应用版本更新功能这一块的实现. 一个好的应用软件都是需要好的维护,从初出版本到最后精品,这个过程需要版本不停的更新,那么如何让用户第一时间获取最新的应用安装包呢?那么就要求我们从第一个版本就要实现升级模块这一功能. 自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语:最新版本的url等).然后我们给出提示框,用户点击开始下载,下载完成开始覆盖安装程序,这样用户的应