Android applications to achieve Automatic Updates is relatively simple, here with you introduce.
1. Web Interface
An interface needs to be provided for the client to query for update status and to notify the client of a new APK address when an update is required.
The interface parameters are as follows:
Package package name because there are times when the same application package name is packaged
Version number, which is the Versioncode in the Android manifest file
Channel channel number
OS operating system, Android/ios. iOS is reserved here only.
The reason for passing in these fields is to meet the server-side package:
Package, channel, OS equals, and server-side version is larger than the client incoming version
The code is as follows:
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 ').
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. Database Design
Because the web side is using Django, it is easy to give the operation of the students can operate the background interface, as follows:
Note that the elements of the red box, operators in the upload, is not allowed to modify, but by the program automatically parse apk file after filling in.
The specific analytic method, which we will give later.
and the corresponding models code is as follows:
Class Package (models. Model):
FILE = models. Filefield (U ' files ', upload_to=config. Package_upload_path)
Package = models. Charfield (U ' package name ', max_length=255, Blank=true, default= ')
Version = Models. Integerfield (U "version number", Blank=true, Default=0, Null=true)
Channel = models. Charfield (U "Channel", max_length=128, Blank=true, default= ')
Status = Models. Integerfield (U ' update status ', Default=config. Package_status_not_update,
Choices=config. Package_update_status)
info = models. TextField (u ' notification info ', blank=true, Null=true)
OS = models. Charfield (U ' os ', 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):
# After the file is uploaded successfully, the filename will be added to the Package_upload_path 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 "File"
3. apk File Resolution
def parse_apk_info (Apk_path, tmp_dir= '/tmp '):
"""
Get package name, version, channel:
{' Version ': ', ' Channel ': ' Cn_main ', ' package ': ' Com.fff.xxx '}
:p Aram 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%s '% (Jar_path, Abs_apk_path, Dst_dir)
If Isinstance (cmd, Unicode):
cmd = Cmd.encode (' UTF8 ')
# Execute
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
Of course, as you can see, we need to rely on the apktool.jar of this document, which we are able to download online.