日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

android 如何使用服务器进行版本更新

發(fā)布時(shí)間:2024/4/15 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 如何使用服务器进行版本更新 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


今天,簡(jiǎn)單講講android里如何在app內(nèi)部直接使用服務(wù)器進(jìn)行版本更新。

昨天,我講了如何使用應(yīng)用市場(chǎng)進(jìn)行版本更新。但是使用應(yīng)用市場(chǎng)進(jìn)行版本更新存在一個(gè)問題,就是app無法獲取應(yīng)用市場(chǎng)里app的版本信息,所以使用應(yīng)用市場(chǎng)進(jìn)行版本更新時(shí),需要搭一個(gè)服務(wù)器給app可以獲取到應(yīng)用市場(chǎng)最新的app的版本信息。

這里大家其實(shí)想到了吧,既然可以通過服務(wù)器獲取app的版本信息,那么也可以直接通過服務(wù)器下載最新的app進(jìn)行版本更新,目前我看到大部分app是這樣做的,比如應(yīng)用寶,支付寶這些app。我之前查找了版本更新的資料也是這些內(nèi)容,這里記錄一下。


一.版本的基礎(chǔ)知識(shí)

????????版本控制的屬性包括versionCode和versionName。

(一)versionCode

????????版本號(hào)(versionCode)是相對(duì)比較重要的一個(gè)屬性。versionCode是一個(gè)Integer類型的值。所以大家在設(shè)置的時(shí)候,不要將versionCode設(shè)置的太大,最好不要超過Integer的取值范圍(當(dāng)然一般也是不會(huì)超過的),一般大家在發(fā)布自己的第一個(gè)應(yīng)用到市場(chǎng)的時(shí)候,版本取值為1(versionCode=1),這也是目前典型和普遍的做法。然后,每次發(fā)布更新版本時(shí)可以遞增versionCode的值。

(二)versionName

????????版本名(versionName)一個(gè)值為String類型的屬性,一般和VersionCode成對(duì)出現(xiàn)。VersionCode是方便程序開發(fā)者運(yùn)行和維護(hù)Application而設(shè)置的一個(gè)有效的值。versionName是一個(gè)版本的描述,給用戶看的,也是用戶放在各個(gè)第3方平臺(tái)上提供給使用者看的一個(gè)版本名,可以說是對(duì)VersionCode的解釋和描述。一般格式可以為:1.1.2。(major.minor.point)的形式。

(三)版本控制小結(jié)

????????版本號(hào)(versionCode)是用于判斷是否升級(jí)的,一般每次版本更新,版本號(hào)加一。如果獲取服務(wù)器上的版本號(hào)比檢測(cè)到本程序的版本號(hào)高,那么提示升級(jí)。
版本名(versionName)用于顯示版本改變的幅度大小,比如從2.0.1改變?yōu)?.0.2可能只是修改了一個(gè)很小的debug,如果改變?yōu)?.1.0可能是新增了一些功能,如果改變?yōu)?.0.0可能是有很大幅度的修改,比如很多UI界面或功能的添加!
????????也就是版本號(hào)用于判斷是否可以升級(jí),而版本名用于顯示給用戶看!

(四)版本控制的文件位置

????????這個(gè)要區(qū)分你是用Eclipse開發(fā)還是Studio開發(fā)。
????????在Eclipse中本控制的屬性的位置是Manifest.xml中,如:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"android:versionCode="3"android:versionName="1.2.1"package="com.example.updateDemo"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme">。。。</application></manifest>

上面表示android的第三個(gè)版本程序,版本名:1.2.1

????????在Android Studio呢?也是可以在Manifest.xml中定義versionCode和versionName,但是這里設(shè)置是無效的!
需要在程序的build.grade文件中設(shè)置,圖解:

上面表示android的第三個(gè)版本程序,版本名:3.0.1

(五)版本信息的獲取,代碼

這里指的是獲取運(yùn)行中的程序的版本號(hào),代碼如下:

/** 獲取當(dāng)前程序的版本名*/ private String getVersionName() throws Exception{//獲取packagemanager的實(shí)例PackageManager packageManager = getPackageManager();//getPackageName()是你當(dāng)前類的包名,0代表是獲取版本信息PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);Log.e("TAG","版本號(hào)"+packInfo.versionCode);Log.e("TAG","版本名"+packInfo.versionName);return packInfo.versionName; }

/** 獲取當(dāng)前程序的版本號(hào)*/ private int getVersionCode() throws Exception{//獲取packagemanager的實(shí)例PackageManager packageManager = getPackageManager();//getPackageName()是你當(dāng)前類的包名,0代表是獲取版本信息PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);Log.e("TAG","版本號(hào)"+packInfo.versionCode);Log.e("TAG","版本名"+packInfo.versionName);return packInfo.versionCode; }

簡(jiǎn)單講講,其實(shí)版本更新就是首先獲取到服務(wù)器的版本號(hào)與版本名稱,然后獲取app自己的版本號(hào)和版本名稱,進(jìn)行比較。如果服務(wù)器的版本號(hào)大于app自己的版本號(hào),那么就進(jìn)行http請(qǐng)求獲取服務(wù)器的apk,進(jìn)行下載。下載完成后就直接覆蓋安裝。

下面舉一個(gè)使用服務(wù)器進(jìn)行版本更新的例子:

該小程序的特點(diǎn)是,當(dāng)有更新時(shí),會(huì)彈出一個(gè)提示框,點(diǎn)擊確定,則在通知來創(chuàng)建一個(gè)進(jìn)度條進(jìn)行下載,點(diǎn)擊取消,則取消更新。

以下是詳細(xì)代碼:

1.創(chuàng)建布局文件notification_item.xml,用于在通知欄生成一個(gè)進(jìn)度條和下載圖標(biāo)。

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:padding="3dp" ><ImageViewandroid:id="@+id/notificationImage"android:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@android:drawable/stat_sys_download" /><TextViewandroid:id="@+id/notificationTitle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_toRightOf="@id/notificationImage"android:paddingLeft="6dp"android:textColor="#FF000000" /><TextViewandroid:id="@+id/notificationPercent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/notificationImage"android:paddingTop="2dp"android:textColor="#FF000000" /><ProgressBarandroid:id="@+id/notificationProgress"style="@style/ProgressBarHorizontal_color"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignLeft="@id/notificationTitle"android:layout_alignParentRight="true"android:layout_alignTop="@id/notificationPercent"android:layout_below="@id/notificationTitle"android:paddingLeft="6dp"android:paddingRight="3dp"android:paddingTop="2dp" /></RelativeLayout>

2.創(chuàng)建AppContext類,該類繼承自Application。

package com.test.application;import android.app.Application; import android.content.Context;import com.test.update.config.Config;public class AppContext extends Application {private static AppContext appInstance;private Context context;public static AppContext getInstance() {return appInstance;}@Overridepublic void onCreate() {// TODO Auto-generated method stubsuper.onCreate();appInstance = this;context = this.getBaseContext(); // // 獲取當(dāng)前版本號(hào) // try { // PackageInfo packageInfo = getApplicationContext() // .getPackageManager().getPackageInfo(getPackageName(), 0); // Config.localVersion = packageInfo.versionCode; // Config.serverVersion = 1;// 假定服務(wù)器版本為2,本地版本默認(rèn)是1 // } catch (NameNotFoundException e) { // e.printStackTrace(); // }initGlobal();}public void initGlobal() {try {Config.localVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode; // 設(shè)置本地版本號(hào)Config.serverVersion = 2;// 假定服務(wù)器版本為2,本地版本默認(rèn)是1--實(shí)際開發(fā)中是從服務(wù)器獲取最新版本號(hào),android具體與后端的交互見我另///外的博文} catch (Exception ex) {ex.printStackTrace();}} }

3.創(chuàng)建配置文件類Config.java,在這個(gè)類里面定義一些與版本相關(guān)的常量

package com.test.update.config;public class Config {//版本信息public static int localVersion = 0;public static int serverVersion = 0;/* 下載包安裝路徑 */ public static final String savePath = "/sdcard/test/"; public static final String saveFileName = savePath + "test.apk"; }

4.編寫更新服務(wù)類UpdateServcie.java

package com.test.update;import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL;import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.widget.RemoteViews;import com.test.update.config.Config;public class UpdateService extends Service {// 標(biāo)題private int titleId = 0;// 文件存儲(chǔ)private File updateDir = null;private File updateFile = null;// 下載狀態(tài)private final static int DOWNLOAD_COMPLETE = 0;private final static int DOWNLOAD_FAIL = 1;// 通知欄private NotificationManager updateNotificationManager = null;private Notification updateNotification = null;// 通知欄跳轉(zhuǎn)Intentprivate Intent updateIntent = null;private PendingIntent updatePendingIntent = null;/**** 創(chuàng)建通知欄*/RemoteViews contentView;// 這樣的下載代碼很多,我就不做過多的說明int downloadCount = 0;int currentSize = 0;long totalSize = 0;int updateTotalSize = 0;// 在onStartCommand()方法中準(zhǔn)備相關(guān)的下載工作:@SuppressWarnings("deprecation")@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 獲取傳值titleId = intent.getIntExtra("titleId", 0);// 創(chuàng)建文件if (android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState())) {updateDir = new File(Environment.getExternalStorageDirectory(),Config.saveFileName);updateFile = new File(updateDir.getPath(), getResources().getString(titleId) + ".apk");}this.updateNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);this.updateNotification = new Notification();// 設(shè)置下載過程中,點(diǎn)擊通知欄,回到主界面updateIntent = new Intent(this, UpdateActivity.class);updatePendingIntent = PendingIntent.getActivity(this, 0, updateIntent,0);// 設(shè)置通知欄顯示內(nèi)容updateNotification.icon = R.drawable.ic_launcher;updateNotification.tickerText = "開始下載";updateNotification.setLatestEventInfo(this, "QQ", "0%",updatePendingIntent);// 發(fā)出通知updateNotificationManager.notify(0, updateNotification);// 開啟一個(gè)新的線程下載,如果使用Service同步下載,會(huì)導(dǎo)致ANR問題,Service本身也會(huì)阻塞new Thread(new updateRunnable()).start();// 這個(gè)是下載的重點(diǎn),是下載的過程return super.onStartCommand(intent, flags, startId);}@Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stubreturn null;}@SuppressLint("HandlerLeak")private Handler updateHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case DOWNLOAD_COMPLETE:// 點(diǎn)擊安裝PendingIntentUri uri = Uri.fromFile(updateFile);Intent installIntent = new Intent(Intent.ACTION_VIEW);installIntent.setDataAndType(uri,"application/vnd.android.package-archive");updatePendingIntent = PendingIntent.getActivity(UpdateService.this, 0, installIntent, 0);updateNotification.defaults = Notification.DEFAULT_SOUND;// 鈴聲提醒updateNotification.setLatestEventInfo(UpdateService.this,"QQ", "下載完成,點(diǎn)擊安裝。", updatePendingIntent);updateNotificationManager.notify(0, updateNotification);// 停止服務(wù)stopService(updateIntent);case DOWNLOAD_FAIL:// 下載失敗updateNotification.setLatestEventInfo(UpdateService.this,"QQ", "下載完成,點(diǎn)擊安裝。", updatePendingIntent);updateNotificationManager.notify(0, updateNotification);default:stopService(updateIntent);}}};public long downloadUpdateFile(String downloadUrl, File saveFile)throws Exception {HttpURLConnection httpConnection = null;InputStream is = null;FileOutputStream fos = null;try {URL url = new URL(downloadUrl);httpConnection = (HttpURLConnection) url.openConnection();httpConnection.setRequestProperty("User-Agent", "PacificHttpClient");if (currentSize > 0) {httpConnection.setRequestProperty("RANGE", "bytes="+ currentSize + "-");}httpConnection.setConnectTimeout(10000);httpConnection.setReadTimeout(20000);updateTotalSize = httpConnection.getContentLength();if (httpConnection.getResponseCode() == 404) {throw new Exception("fail!");}is = httpConnection.getInputStream();fos = new FileOutputStream(saveFile, false);byte buffer[] = new byte[4096];int readsize = 0;while ((readsize = is.read(buffer)) > 0) {fos.write(buffer, 0, readsize);totalSize += readsize;// 為了防止頻繁的通知導(dǎo)致應(yīng)用吃緊,百分比增加10才通知一次if ((downloadCount == 0)|| (int) (totalSize * 100 / updateTotalSize) - 10 > downloadCount) {downloadCount += 10;updateNotification.setLatestEventInfo(UpdateService.this,"正在下載", (int) totalSize * 100 / updateTotalSize+ "%", updatePendingIntent);/**** 在這里我們用自定的view來顯示Notification*/updateNotification.contentView = new RemoteViews(getPackageName(), R.layout.notification_item);updateNotification.contentView.setTextViewText(R.id.notificationTitle, "正在下載");updateNotification.contentView.setProgressBar(R.id.notificationProgress, 100, downloadCount, false);updateNotificationManager.notify(0, updateNotification);}}} finally {if (httpConnection != null) {httpConnection.disconnect();}if (is != null) {is.close();}if (fos != null) {fos.close();}}return totalSize;}class updateRunnable implements Runnable {Message message = updateHandler.obtainMessage();public void run() {message.what = DOWNLOAD_COMPLETE;try {// 增加權(quán)限<USES-PERMISSION// android:name="android.permission.WRITE_EXTERNAL_STORAGE">;if (!updateDir.exists()) {updateDir.mkdirs();}if (!updateFile.exists()) {updateFile.createNewFile();}// 下載函數(shù),以QQ為例子// 增加權(quán)限<USES-PERMISSION// android:name="android.permission.INTERNET">;long downloadSize = downloadUpdateFile("http://softfile.3g.qq.com:8080/msoft/179/1105/10753/MobileQQ1.0(Android)_Build0198.apk",updateFile);if (downloadSize > 0) {// 下載成功updateHandler.sendMessage(message);} } catch (Exception ex) {ex.printStackTrace();message.what = DOWNLOAD_FAIL;// 下載失敗updateHandler.sendMessage(message);}}} }

5.編寫活動(dòng)類UpdateActivity

package com.test.update;import com.test.update.config.Config;import android.support.v4.app.Fragment; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater;public class UpdateActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);checkVersion();}/*** 檢查更新版本*/public void checkVersion() {if (Config.localVersion < Config.serverVersion) {Log.i("hgncxzy", "==============================");// 發(fā)現(xiàn)新版本,提示用戶更新AlertDialog.Builder alert = new AlertDialog.Builder(this);alert.setTitle("軟件升級(jí)").setMessage("發(fā)現(xiàn)新版本,建議立即更新使用.").setPositiveButton("更新",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {// 開啟更新服務(wù)UpdateService// 這里為了把update更好模塊化,可以傳一些updateService依賴的值// 如布局ID,資源ID,動(dòng)態(tài)獲取的標(biāo)題,這里以app_name為例Intent updateIntent = new Intent(UpdateActivity.this,UpdateService.class);updateIntent.putExtra("titleId",R.string.app_name);startService(updateIntent);}}).setNegativeButton("取消",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {dialog.dismiss();}});alert.create().show();} else {// 清理工作,略去// cheanUpdateFile()}} }

6.添加權(quán)限以及將服務(wù)靜態(tài)加載(在配置文件中加載)。

<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

注冊(cè)服務(wù)

<service android:name="com.test.update.UpdateService" ></service>

完整的AndroidManifest.xml文件如下:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.test.update"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="8"android:targetSdkVersion="8" /><applicationandroid:name="com.test.application.AppContext"android:icon="@drawable/ic_launcher"android:label="@string/app_name" ><activityandroid:name="com.test.update.UpdateActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><service android:name="com.test.update.UpdateService" ></service></application><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /></manifest>

簡(jiǎn)單講講,這個(gè)例子首先在啟動(dòng)app時(shí)彈出版本更新的提示框,點(diǎn)擊更新后,會(huì)發(fā)送http請(qǐng)求下載apk文件,同時(shí)生成一個(gè)通知,每隔%10進(jìn)度時(shí)更新通知,下載完成后,點(diǎn)擊通知欄就可以進(jìn)行版本更新。具體的內(nèi)容比較簡(jiǎn)單,關(guān)于通知的內(nèi)容我會(huì)另寫一篇博客進(jìn)行講解。


源碼下載:https://download.csdn.net/download/bzlj2912009596/10463834


android 如何使用服務(wù)器進(jìn)行版本更新就講完了。


就這么簡(jiǎn)單。

 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的android 如何使用服务器进行版本更新的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。