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

 更新时间:2016年9月20日 19:58  点击:1858
一般的安卓应用都会提供自动更新的功能,让用户方便使用最新的版本,现在我们来讲讲如何实现安卓应用自动更新的功能实例方案,方便大家学习。

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

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,所以可以很方便的给出运营同学可以操作的后台界面,如下:

NewImage

注意红框内的元素,运营同学在上传时,是不允许修改的,而是由程序自动解析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 这个文件,具体大家可以在网上下载。

本文我们来看看使用 Android Emulator 模拟器,如何设置自己的GPS地址位置信息的几个方法,做 Android 开发的朋友可以看下。

使用Android Emulator,可以自己设置GPS地理位置信息,根据Android官方文档的介绍,可以有如下几种方式:

1. 通过命令行:

telnet 5554    # 5554为emulator的console端口
 
geo fix 121.420413 31.215345  # 第一个数值是经度(longitude),第二个数值是纬度(latitude)
# 可从 google maps获取经纬度, https://maps.google.com/

2. 通过Eclipse:


设置路径为:Window > Show View > Other > Emulator Control.
In the Emulator Control panel, enter GPS coordinates under Location Controls as individual lat/long coordinates, with a GPX file for route playback, or a KML file for multiple place marks. (Be sure that you have a device selected in the Devices panel—available from Window > Show View > Other > Devices.)
Using DDMS

3. 通过DDMS:

With the DDMS tool, you can simulate location data a few different ways:
Manually send individual longitude/latitude coordinates to the device.
Use a GPX file describing a route for playback to the device.
Use a KML file describing individual place marks for sequenced playback to the device.

我还是比较喜欢用命令行的方式~
不过,我通常使用HAXM或KVM来加速我的emulator(里面时运行Intel的image),我就发现这些设置方法对我的emulator都没有生效。这个问题曾经困扰了我好几天,后来和一个同事交流时才发现,其实这个设置地理位置信息是依赖于Google API的,而使用Intel的一些image,里面默认时没有Google API的,所以不能生效(即使geo fix命令返回是ok)。所幸的是,Android SDK中从android 4.4开始也直接提供了x86 image的Google APIs。
对于Android 4.3/4.2等的X86镜像,需要通过如下步骤来手动添加Google API的支持。

 代码如下 复制代码
1.  In Android Virtual Device Manager create an AVD with target "Android 4.3/4.2"  (其实就是先使用arm的image)
2.    emulator -avd name_of_avd    (启动arm image)
3.   adb pull /system/etc/permissions/com.google.android.maps.xml     (下载google maps相关文件)
4.    adb pull /system/framework/com.google.android.maps.jar   (下载google maps相关文件)
5.    (optional) Remove the create AVD in Android Virtual Device Manager   (删掉刚才使用的ARM avd,可选)
6.   In Android Virtual Device Manager create an AVD with target "Intel Atom x86 system Image (Intel Corporation) - API Level 18"    (创建Intel x86 image)
8.   emulator -partition-size 1024 -no-snapshot-save -avd name_of_avd   (启动x86 image)
9.   adb remount rw    (让文件系统可写)
10.    adb push com.google.android.maps.xml /system/etc/permissions    (上传google maps相关文件到x86 iamge中)
11.   adb push com.google.android.maps.jar /system/framework   (上传google maps相关文件到x86 iamge中)
12.    Download mkfs.yaffs2.x86  (下载地址:https://android-group-korea.googlecode.com/files/mkfs.yaffs2.x86)
13.   adb push mkfs.yaffs2.x86 /data   (将mkfs.yaffs2.x86传到image里面)
14.   adb shell   (连接到该emualtor的shell)
15.   cd /data
16.    chmod 777 mkfs.yaffs2.x86
17.   ./mkfs.yaffs2.x86 /system system.img            (重新制作system.img文件)
18.    exit  (退出adb shell)
19.    adb pull /data/system.img  (下载制作好的system.img,需要较长时间,耐心等待吧)
20.    Copy system.img into avd directory    (将这个system.img 复制到的你的AVD目录中,覆盖掉原来的system.img,可以先备份原来的)
21.   Reboot emulator  (重启emulator,即可使用到新的system.img)



我第一次这么操作时,在上传google maps文件到x86 image中时,出现了如下的错误:

jay@jay-linux:~/adt-bundle-linux-x86_64-20140321/sdk$ adb push com.google.android.maps.xml /system/etc/permissions
failed to copy 'com.google.android.maps.xml' to '/system/etc/permissions/com.google.android.maps.xml': Out of memory

后来发现原因是,原本的system.img的容量只够存放自己的东西,里面已经存不下其他东西了。所以,在启动x86 AVD时,要用”emulator -partition-size 1024 avd-for-x86“命令来调整/data目录的大小为1024MB。

参考资料:


android官方文档:http://developer.android.com/guide/topics/location/strategies.html
Intel image使用Google Maps API: http://38911bytes.blogspot.de/2012/03/how-to-use-google-maps-api-in-android.html
http://stackoverflow.com/questions/9857325/google-maps-sdk-with-new-intel-atom-x86-emulator

下面来给各位介绍android studio升级失败提示 Connection failed解决方法,希望文章可以给各位带来帮助.

关于这个问题,查了不少地方,发现解决方法都差不多,但或多或少有些问题或没说清楚。关于在windows系统中的解决方法,基本没什么问题,都是如下修改:

在Android Studio安装目录“/bin/studio.exe.vmoptions”文件中追加以下几行


-Djava.net.preferIPv4Stack=true
-Didea.updates.url=http://dl.google.com/android/studio/patches/updates.xml
-Didea.patches.url=http://dl.google.com/android/studio/patches/

但有点要注意,64位系统就应该修改“/bin/studio64.exe.vmoptions”这个文件。
而下面主要说明修改mac中的升级问题:

在Mac和Linux版本中,网上提供的解决办法,差不多都是如下修改:
直接修改环境变量:


$ export REQUIRED_JVM_ARGS="-Didea.updates.url=http://dl.google.com/android/studio/patches/updates.xml -Didea.patches.url=http://dl.google.com/android/studio/patches/"
$ bin/studio

此方法多次尝试,均以失败告终。最后不得不自行想办法解决,发现如下修改可解决这个问题:

在“/Applications/Android Studio.app”中,右键点击“显示包内容”,打开“/bin/idea.vmoptions”文件,在后面追加入windows中的内容,即:

-Djava.net.preferIPv4Stack=true
-Didea.updates.url=http://dl.google.com/android/studio/patches/updates.xml
-Didea.patches.url=http://dl.google.com/android/studio/patches/
后保存退出,重新打开Android Studio,Check for Updates …就可以看到升级提示了。

注:此方法只是自己摸索尝试在本机上可行,非官方提供,失败勿喷,谢谢!a

hosts文件以前小编以为只有电脑才有呢,没想到手机也有hosts文件了,下面我来为各位介绍Android修改hosts文件的方法介绍

有朋友问Android怎么修改Hosts?对于这个问题,由于手头并没有Android设备,所以只能从网上搜罗了几个方法,如果有朋友有更好的方法,不妨留言补充。

本文介绍三种Android手机修改hosts文件的方法,但修改hosts文件一定要谨慎:Android手机hosts文件的换行符必须是n而不是windows的rn,使用Notepad++打开hosts文件,依次点击菜单中的“视图–显示符号–显示所有字符”,如果行末是LF就没问题,CR LF结束则需要替换所有的CR LF为LF。

Android手机hosts文件路径:/system/etc/hosts

修改hosts方法一:需重启

修改host文件首先需要Android手机获取Root权限

使用Root Explorer管理器或ES文件浏览器装载/system可写状态,找到/system/etc/hosts的文件,使用文本编辑器打开编辑后保存
保存后重启手机即可生效

修改hosts方法二:不需重启

将hosts文件拷贝到电脑,电脑端修改后复制回手机,这种方法不需要重启

修改hosts方法三

各种android市场中寻找修改hosts的app,例如:

hosts 助手
smartHosts
至于iOS设备如何修改hosts,可能就需要越狱了,有些麻烦,这里暂且不提。本人目前使用的苹果设备用到的google服务不多,如果有朋友有什么好的方法,也可以留言告诉我

Android x86 即运行于 x86 PC上的Android操作系统,目前已经支持大部分安卓程序。本文我们来分享一下ndroid X86 4.4 使用体验组图,有兴趣的朋友可以去官方下载安装。

Android X86 4.4 不久前发布,这是正式发布版本,官方网址:http://www.android-x86.org/,有兴趣的朋友可以去下载(官网好像被墙了,唉)

1

2

3

4

7

5

6

8

9

10

12

11

13

[!--infotagslink--]

相关文章

  • 苹果告别“高大上”,越来越向安卓和中国用户靠近

    “一起,让我们将这个世界变得更好。”苹果首席执行官蒂姆 库克对着台下5000多名开发者说道,声音略有些沙哑和颤抖。...2016-07-04
  • php语言实现redis的客户端

    php语言实现redis的客户端与服务端有一些区别了因为前面介绍过服务端了这里我们来介绍客户端吧,希望文章对各位有帮助。 为了更好的了解redis协议,我们用php来实现...2016-11-25
  • jQuery+jRange实现滑动选取数值范围特效

    有时我们在页面上需要选择数值范围,如购物时选取价格区间,购买主机时自主选取CPU,内存大小配置等,使用直观的滑块条直接选取想要的数值大小即可,无需手动输入数值,操作简单又方便。HTML首先载入jQuery库文件以及jRange相关...2015-03-15
  • JS实现的简洁纵向滑动菜单(滑动门)效果

    本文实例讲述了JS实现的简洁纵向滑动菜单(滑动门)效果。分享给大家供大家参考,具体如下:这是一款纵向布局的CSS+JavaScript滑动门代码,相当简洁的手法来实现,如果对颜色不满意,你可以试着自己修改CSS代码,这个滑动门将每一...2015-10-21
  • jQuery+slidereveal实现的面板滑动侧边展出效果

    我们借助一款jQuery插件:slidereveal.js,可以使用它控制面板左右侧滑出与隐藏等效果,项目地址:https://github.com/nnattawat/slideReveal。如何使用首先在页面中加载jquery库文件和slidereveal.js插件。复制代码 代码如...2015-03-15
  • PHP+jQuery翻板抽奖功能实现

    翻板抽奖的实现流程:前端页面提供6个方块,用数字1-6依次表示6个不同的方块,当抽奖者点击6个方块中的某一块时,方块翻转到背面,显示抽奖中奖信息。看似简单的一个操作过程,却包含着WEB技术的很多知识面,所以本文的读者应该熟...2015-10-21
  • SQLMAP结合Meterpreter实现注入渗透返回shell

    sqlmap 是一个自动SQL 射入工具。它是可胜任执行一个广泛的数据库管理系统后端指印, 检索遥远的DBMS 数据库等,下面我们来看一个学习例子。 自己搭建一个PHP+MYSQ...2016-11-25
  • 安卓开发之设置密码只能输入字母和数字的组合

    设置登录密码我们一般会有限制的如由什么组合了,下面我们来看一篇关于安卓开发之设置密码只能输入字母和数字的组合方法,具体的细节如下所示。 无论是电脑还是手机...2016-09-20
  • PHP实现今天是星期几的几种写法

    复制代码 代码如下: // 第一种写法 $da = date("w"); if( $da == "1" ){ echo "今天是星期一"; }else if( $da == "2" ){ echo "今天是星期二"; }else if( $da == "3" ){ echo "今天是星期三"; }else if( $da == "4"...2013-10-04
  • 原生js实现fadein 和 fadeout淡入淡出效果

    js里面设置DOM节点透明度的函数属性:filter= "alpha(opacity=" + value+ ")"(兼容ie)和opacity=value/100(兼容FF和GG)。 先来看看设置透明度的兼容性代码: 复制代码 代码如下: function setOpacity(ele, opacity) { if (...2014-06-07
  • 自动设置安卓手机wifi代理的PowerShell脚本

    这篇文章主要介绍了自动设置安卓手机wifi代理的PowerShell脚本,帮助大家进行抓包测试,感兴趣的朋友可以了解下...2020-10-17
  • 安卓开发之Intent传递Object与List教程

    下面我们一起来看一篇关于 安卓开发之Intent传递Object与List的例子,希望这个例子能够为各位同学带来帮助。 Intent 不仅可以传单个的值,也可以传对象与数据集合...2016-09-20
  • Android中用HttpClient实现Http请求通信

    本文我们需要解决的问题是如何实现Http请求来实现通信,解决Android 2.3 版本以后无法使用Http请求问题,下面请看正文。 Android开发中使用HttpClient来开发Http程序...2016-09-20
  • mysql存储过程实现split示例

    复制代码 代码如下:call PROCEDURE_split('分享,代码,片段',',');select * from splittable;复制代码 代码如下:drop PROCEDURE if exists procedure_split;CREATE PROCEDURE `procedure_split`( inputstring varc...2014-05-31
  • 安卓4.1系统手机怎么设置用wifi上网

    wifi上网 几乎是不需要什么设置了,我们只要简单的输入wifi密码与用户名就可以自动连接wifi上网了,下面我以安卓4.1系统为实例 具体步骤 1.在安卓手机中点击“...2016-09-20
  • EMUI11上手体验 新颜值/新功能/新体验

    EMUI11值得升级吗?好不好用?下面小编带来EMUI11上手体验,一起来看看手机鸿蒙OS的提前预演...2020-12-08
  • PHP+Mysql+Ajax+JS实现省市区三级联动

    基本思想就是:在JS动态创建select控件的option,通过Ajax获取在PHP从SQL数据库获取的省市区信息,代码有点长,但很多都是类似的,例如JS中省、市、区获取方法类似,PHP中通过参数不同执行不同的select语句。index.html代码:复制...2014-05-31
  • 小爱同学5.0新增了哪些机型 小爱同学5.0新功能介绍

    小爱同学5.0即将发布,据已知报道小爱同学5.0将新增机型,跟着小编一起来看看吧,顺便了解下即将都有哪些新功能面市吧...2020-12-08
  • JS实现程序暂停与继续功能代码解读

    下面代码用JS实现了程序的暂停与继续 复制代码 代码如下: <script type="text/javascript"> /*Javascript中暂停功能的实现 Javascript本身没有暂停功能(sleep不能使用)同时 vbscript也不能使用doEvents,故编写此函数实...2013-10-13
  • CS 1.6成功移植安卓智能手机 附下载地址及安装教程

    Reddit上的高手成功将CS 1.6移植到了安卓智能手机上,而且95-100%兼容原作,几乎无可挑剔,下面小编为大家带来下载地址及安装教程,来看看吧...2016-07-04