Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android手機 >> Android手機綜合 >> 實現安卓app自動更新功能實例方案

實現安卓app自動更新功能實例方案

編輯:Android手機綜合

  一般的安卓應用都會提供自動更新的功能,讓用戶方便使用最新的版本,現在我們來講講如何實現安卓應用自動更新的功能實例方案,方便大家學習。

  安卓應用實現自動更新比較簡單,這裡跟大家介紹下。

  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,所以可以很方便的給出運營同學可以操作的後台界面,如下:

實現安卓app自動更新功能實例方案    三聯

  注意紅框內的元素,運營同學在上傳時,是不允許修改的,而是由程序自動解析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 這個文件,具體大家可以在網上下載。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved