应用宝省流量更新介绍
应用宝省流量更新(SDK),是应用宝提供给开发者轻松实现应用省流量更新的功能,可以帮助开发者缩短更新过程,提高应用下载量。在每次应用升级更新时,只需更新部分数据而无需下载完整大小的安装包,帮用户节省了流量,也大大提高了产品升级速度。
注册开发者
进入腾讯开放平台
点击
移动应用
,进入登录界面使用QQ号码登录或注册新账号,登录后进入注册开发者界面,可选择注册为个人或公司开发者
创建应用
注册成功后,进入管理中心,点击
创建应用
填写应用信息,提交审核
实现省流量更新
邮件申请渠道号
添加引用TMAssistantSDK_selfUpdate_201407240950
修改AndroidManifest.xml
- 添加服务
<service android:name="com.tencent.tmassistantsdk.downloadservice.TMAssistantDownloadSDKService" android:exported="false" android:process=":TMAssistantDownloadSDKService" > </service>
- 添加权限
<!-- 网络请求 --><uses-permission android:name="android.permission.INTERNET" /><!-- 判断当前网络类型 --><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><!-- 写外部存储卡 --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
添加检查更新代码
SoftwareUpgrade.java
软件升级管理对象
import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.os.Handler;import android.os.Looper;import android.view.View;import com.tencent.tmassistantsdk.common.TMAssistantDownloadSDKTaskState;import com.tencent.tmassistantsdk.selfUpdateSDK.ITMSelfUpdateSDKListener;import com.tencent.tmassistantsdk.selfUpdateSDK.TMSelfUpdateSDK;import com.tencent.tmassistantsdk.selfUpdateSDK.TMSelfUpdateSDKUpdateInfo;import java.text.DecimalFormat;/** * 软件升级,利用应用宝的接口进行软件版本检查、软件升级 */public class SoftwareUpgrade { private Context ctx = null; private static final String TAG = "SoftwareUpgrade"; /** * AppID,应用上线后获得 */ private static final long APP_ID = 0000000000; /** * 渠道ID,邮件申请省流量更新后获得 */ private static final String CHANNEL_ID = "0000000"; /** * 省流量更新SDK */ private TMSelfUpdateSDK sdk = null; /** * 线程操作对象 */ private Handler handler = null; /** * 是否需要提醒更新(自动检查更新时需要) */ private boolean isNeedNotify = false; /** * 软件更新的信息 */ private SoftwareUpdateInfo updateInfo = null; public static SoftwareUpdateInfo getUpdateInfo() { if (instance != null) { return instance.updateInfo; } return null; } /** * 更新提示对话框 */ private UpgradeDialog updateDialog = null; /** * 单例模式 */ private static SoftwareUpgrade instance = null; public static SoftwareUpgrade getInstance() { if (instance == null) { instance = new SoftwareUpgrade(); } if (instance.sdk == null) { // 初始化失败,无法使用自动更新功能 instance = null; } return instance; } /** * 初始化检查更新(软件启动时调用) */ private SoftwareUpgrade() { // 得到主线程的Looper实例 Looper looper = Looper.getMainLooper(); handler = new Handler(looper); try { sdk = TMSelfUpdateSDK.getInstance(); sdk.initTMSelfUpdateSDK(App.getInstance().getApplicationContext() , APP_ID, CHANNEL_ID, selfUpdateSDKListener); } catch (Exception ex) { sdk = null; LogUtil.d(TAG, "Init TMSelfUpdateSDK failed!"); } } /** * 释放(退出软件时调用) */ public static void release() { if (instance != null && instance.sdk != null) { instance.sdk.destroySelfUpdateSDK(instance.selfUpdateSDKListener); instance = null; } } /** * 检查软件是否需要更新(静默检查,不弹出提示对话框) */ public static void checkNeedUpdate() { if (instance != null && instance.sdk != null) { instance.isNeedNotify = false; instance.sdk.checkNeedUpdate(); } } /** * 检查软件是否需要更新(若有更新,则提醒用户更新) */ public static void checkNeedUpdateNeedNotify(Context context) { if (instance != null && instance.sdk != null) { instance.ctx = context; instance.isNeedNotify = true; instance.sdk.checkNeedUpdate(); } } /** * 开始省流量更新 * 1、弹出更新信息对话框,询问用户是否更新 * 2、若未安装应用宝,询问用户是否安装 * 3、跳转到应用宝更新软件 * @param ctx */ public static void startSaveUpdate(final Context ctx) { if (instance != null && instance.sdk != null) { instance.updateDialog = new UpgradeDialog(ctx); instance.updateDialog.setVersion(instance.updateInfo.newVersion); instance.updateDialog.setUpdateContent(instance.updateInfo.updateContent); instance.updateDialog.setUpdateSize(instance.updateInfo.updateSize); instance.updateDialog.setUpdateButtonOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { // 检查应用宝是否安装 int yybInstalled = instance.sdk.checkYYBInstalled(); if (yybInstalled == TMAssistantDownloadSDKTaskState.UN_INSTALLED) { // 未安装应用宝,提示用户需要安装应用宝 DialogUtil.showWarnDialog(ctx, R.string.msg_no_yyb, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { instance.sdk.startSaveUpdate(ctx); } }); } else { // 打开应用宝更新 instance.sdk.startSaveUpdate(ctx); instance.updateDialog.dismiss(); } } catch (Exception e) { LogUtil.e(e); } } }); } } /** * 省流量更新调用 * 应用宝已经下载安装完毕,回到调用方的页面,调用方可以选择是否调用该方法,call起应用宝下载管理页去更新 */ public static void onResume() { if (instance != null && instance.sdk != null) { instance.sdk.onResume(App.getInstance().getApplicationContext()); } } private ITMSelfUpdateSDKListener selfUpdateSDKListener = new ITMSelfUpdateSDKListener() { /** * 使用sdk自更新前,调用方法checkNeedUpdate检查是否需要更新时回调 * 如果有更新包,则返回新包大小、增量包大小 * @param tmSelfUpdateSDKUpdateInfo 这个参数,当继续往下走,下载 完成时,要传回来给接口 */ @Override public void OnCheckNeedUpdateInfo(final TMSelfUpdateSDKUpdateInfo tmSelfUpdateSDKUpdateInfo) { updateInfo = new SoftwareUpdateInfo(); if (tmSelfUpdateSDKUpdateInfo != null && tmSelfUpdateSDKUpdateInfo.getStatus() == TMSelfUpdateSDKUpdateInfo.STATUS_OK && tmSelfUpdateSDKUpdateInfo.getNewApkSize() > 0) { // 解析版本号 String url = tmSelfUpdateSDKUpdateInfo.getUpdateDownloadUrl(); String version = ""; if (url != null && url.length() > 0) { String[] temp = url.split("_"); if (temp.length > 2) { version = temp[1]; } } updateInfo.hasNewVersion = true; updateInfo.newVersion = version; updateInfo.updateContent = tmSelfUpdateSDKUpdateInfo.getNewFeature(); updateInfo.updateSize = getDataSize(tmSelfUpdateSDKUpdateInfo.getNewApkSize()); } if (isNeedNotify) { // 如果需要更新,则跳转到关于界面 if (updateInfo.hasNewVersion) { DialogUtil.showWarnDialog(ctx, R.string.msg_has_new_version, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // 跳转到关于界面进行更新 MainActivity mainActivity = (MainActivity) ctx; if (mainActivity != null) { mainActivity.startActivity(new Intent(mainActivity, AboutActivity.class)); } } }); } else { App.getInstance().toast(R.string.msg_current_lastest_version_software); } } } /** * 省流量更新时回调 * 检查应用宝状态,若未安装,则开始自动安装 * @param url 指定任务的url * @param state 下载状态 * @param errorCode 错误码 * @param errorMsg 错误描述 */ @Override public void OnDownloadYYBStateChanged(String url, final int state,int errorCode, String errorMsg) { handler.post(new Runnable() { @Override public void run() { switch (state) { case TMAssistantDownloadSDKTaskState.DownloadSDKTaskState_WAITING: if (updateDialog != null) { updateDialog.startProgress(); updateDialog.setProgressText(R.string.msg_waiting_install_yyb); } break; case TMAssistantDownloadSDKTaskState.DownloadSDKTaskState_DOWNLOADING: // 下方提供进度更新显示,此处不需要// if (updateDialog != null) {// updateDialog.setProgressText("正在下载应用宝");// } break; case TMAssistantDownloadSDKTaskState.DownloadSDKTaskState_PAUSED:// if (updateDialog != null) {// updateDialog.setProgressText("应用宝下载暂停");// } break; case TMAssistantDownloadSDKTaskState.DownloadSDKTaskState_SUCCEED: if (updateDialog != null) { updateDialog.setProgressText(R.string.msg_download_yyb_success); updateDialog.dismiss(); } break; case TMAssistantDownloadSDKTaskState.DownloadSDKTaskState_FAILED: if (updateDialog != null) { updateDialog.dismiss(); App.getInstance().toast(R.string.msg_download_yyb_failed); } break; default:// App.getInstance().toast(state); break; } } }); } /** * 省流量更新时回调 * 下载应用宝的进度 * @param url 指定任务的url * @param receiveDataLen 已经接收的数据长度 * @param totalDataLen 全部需要接收的数据长度(如果无法获取目标文件的总长度,此参数返回-1) */ @Override public void OnDownloadYYBProgressChanged(final String url,final long receiveDataLen, final long totalDataLen) { handler.post(new Runnable() { @Override public void run() { if (updateDialog != null) { updateDialog.setProgress((int) (receiveDataLen * 100 / (double) totalDataLen)); updateDialog.setProgressText( getDataSize(receiveDataLen) + " / " + getDataSize(totalDataLen)); } } }); } }; /** * 计算数据大小,将bit转换为k或M的单位输出 * @param dataSize * @return */ private String getDataSize(long dataSize) { long kb = dataSize / 1024; // 单位k if (kb < 1024) { return kb + "k"; } double mb = dataSize / 1024.0 / 1024.0 + 0.05; // 转换为M,保留一位小数,四舍五入 return new DecimalFormat(".0").format(mb) + "M"; } /** * 软件更新信息 */ public class SoftwareUpdateInfo { /** * 是否有新版本 */ public boolean hasNewVersion = false; /** * 新版本号 */ public String newVersion = ""; /** * 更新内容 */ public String updateContent = ""; /** * 更新大小 */ public String updateSize = ""; }}
UpgradeDialog.java
软件升级信息对话框
import android.app.AlertDialog;import android.content.Context;import android.support.annotation.StringRes;import android.view.LayoutInflater;import android.view.View;import android.widget.Button;import android.widget.LinearLayout;import android.widget.ProgressBar;import android.widget.TextView;public class UpgradeDialog { private Context ctx = null; private AlertDialog dialog = null; private TextView tvVersion = null; private TextView tvUpdateContent = null; private LinearLayout layoutUpdateButton = null; private Button btnNotUpdate = null; private Button btnUpdate = null; private LinearLayout layoutUpdateProgress = null; private ProgressBar progressBar = null; private TextView tvUpdateProgress = null; public UpgradeDialog(Context context) { ctx = context; LayoutInflater layoutInflater = LayoutInflater.from(ctx); View view = layoutInflater.inflate(R.layout.dialog_notify_update, null); if (view != null) { tvVersion = (TextView) view.findViewById(R.id.tv_version); tvUpdateContent = (TextView) view.findViewById(R.id.tv_update_content); layoutUpdateButton = (LinearLayout) view.findViewById(R.id.layout_update_button); btnNotUpdate = (Button) view.findViewById(R.id.btn_not_update); btnUpdate = (Button) view.findViewById(R.id.btn_update); layoutUpdateProgress = (LinearLayout) view.findViewById(R.id.layout_update_progress); progressBar = (ProgressBar) view.findViewById(R.id.progressBar); tvUpdateProgress = (TextView) view.findViewById(R.id.tv_update_progress); AlertDialog.Builder builder = new AlertDialog.Builder(ctx); builder.setTitle(R.string.layout_update_software_notify); builder.setView(view); dialog = builder.create(); dialog.setCancelable(false); dialog.show(); btnNotUpdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog.dismiss(); } }); progressBar.setMax(100); } } public void setVersion(String version) { if (tvVersion != null) { tvVersion.setText(version); } } public void setUpdateContent(String updateContent) { if (tvUpdateContent != null) { tvUpdateContent.setText(updateContent); } } public void setUpdateSize(String newApkSize) { if (btnUpdate != null) { btnUpdate.setText(ctx.getString(R.string.layout_update_software_update_now, newApkSize)); } } public void setUpdateButtonOnClickListener(View.OnClickListener listener) { if (btnUpdate != null) { btnUpdate.setOnClickListener(listener); } } public void dismiss() { if (dialog != null && dialog.isShowing()) { dialog.dismiss(); } } public void setProgress(int value) { if (progressBar != null) { progressBar.setProgress(value); } } public void setProgressText(@StringRes int progress) { if (tvUpdateProgress != null) { tvUpdateProgress.setText(progress); } } public void setProgressText(String progress) { if (tvUpdateProgress != null) { tvUpdateProgress.setText(progress); } } public void startProgress() { if (layoutUpdateProgress != null) { layoutUpdateProgress.setVisibility(View.VISIBLE); } if (progressBar != null) { progressBar.setProgress(0); } if (layoutUpdateButton != null) { layoutUpdateButton.setVisibility(View.GONE); } }}
dialog_notify_update.xml
软件升级提示界面
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="@dimen/app_content_border_size" android:layout_gravity="center"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/layout_update_software_update_content" android:textColor="@color/app_title_textColor" android:textSize="@dimen/app_content_textSize" android:textStyle="bold"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/app_space_size" android:textColor="@color/app_title_textColor" android:textSize="@dimen/app_content_textSize" android:textStyle="bold" android:id="@+id/tv_version"/> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:layout_marginTop="@dimen/app_content_border_size" android:minWidth="@dimen/software_upgrade_scrollbar_min_width" android:minHeight="@dimen/software_upgrade_scrollbar_min_height" android:scrollbars="vertical"> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textColor="@color/app_title_textColor" android:id="@+id/tv_update_content"/> </ScrollView> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginTop="@dimen/app_content_border_size" android:visibility="gone" android:id="@+id/layout_update_progress"> <ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/progressBar" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/app_space_size" android:textColor="@color/app_title_textColor" android:id="@+id/tv_update_progress"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="@dimen/app_content_border_size" android:id="@+id/layout_update_button"> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/layout_update_software_not_update" android:id="@+id/btn_not_update"/> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="@string/layout_update_software_update_now" android:id="@+id/btn_update"/> </LinearLayout></LinearLayout>
MainActivity.xml
主界面中初始化和释放软件升级管理对象
public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mainView = LayoutInflater.from(this).inflate(R.layout.activity_main, null); setContentView(mainView); // 初始化软件更新对象 SoftwareUpgrade softwareUpgrade = SoftwareUpgrade.getInstance(); if (softwareUpgrade == null) { app.setCanAutoUpdate(false); // 公共变量,用于标识自动更新对象是否初始化成功,若不成功,则屏蔽相关功能 app.toast(R.string.msg_init_auto_update_software_failed); } else { app.setCanAutoUpdate(true); // 检查软件更新 if (app.isAutoCheckSoftwareUpdate()) { // 是否开启自动检查更新功能 SoftwareUpgrade.checkNeedUpdateNeedNotify(this); // 弹框提醒更新 } else { SoftwareUpgrade.checkNeedUpdate(); // 不弹框提醒 } } } @Override protected void onDestroy() { // 释放软件更新对象 SoftwareUpgrade.release(); super.onDestroy(); }}
SoftwareSetupFragment.java
软件设置界面,包含“自动检查更新”开关配置,关于。
public class SoftwareSetupFragment extends BaseFragment { @Bind(R.id.btn_auto_check_software_update) ButtonSettingLayout btnAutoCheckSoftwareUpdate; @Bind(R.id.btn_about) ButtonSettingLayout btnAbout; @Override protected int getContentLayoutId() { return R.layout.fragment_software_setup; } /** * 自动检查更新的配置key */ public static final String PREF_AUTO_CHECK_SOFTWARE_UPDATE = "auto_check_software_update"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = super.onCreateView(inflater, container, savedInstanceState); initialize(rootView); return rootView; } @Override protected void initialize(View rootView) { ButterKnife.bind(this, rootView); // 自动检查软件更新 btnAutoCheckSoftwareUpdate.setVisibility(app.isCanAutoUpdate() ? View.VISIBLE : View.GONE); btnAutoCheckSoftwareUpdate.setChecked(app.isAutoCheckSoftwareUpdate()); btnAutoCheckSoftwareUpdate.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { prefs.edit().putBoolean(PREF_AUTO_CHECK_SOFTWARE_UPDATE, isChecked).commit(); app.setAutoCheckSoftwareUpdate(isChecked); } }); // 关于 if (SoftwareUpgrade.getUpdateInfo() != null && SoftwareUpgrade.getUpdateInfo().hasNewVersion) { btnAbout.setIconColor(Color.RED); } btnAbout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { parent.startActivityFromFragment(SoftwareSetupFragment.this, new Intent(getActivity(), AboutActivity.class), 0); } }); } @Override protected void release() { ButterKnife.unbind(this); }}
AboutActivity.java
关于界面,提供软件升级功能
public class AboutActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); btnCheckUpdate.setVisibility(app.isCanAutoUpdate() ? View.VISIBLE : View.GONE); if (SoftwareUpgrade.getUpdateInfo() != null) { if (SoftwareUpgrade.getUpdateInfo().hasNewVersion) { btnCheckUpdate.setText(getString( R.string.layout_update_software_update_now, SoftwareUpgrade.getUpdateInfo().newVersion)); btnCheckUpdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SoftwareUpgrade.startSaveUpdate(AboutActivity.this); } }); } else { btnCheckUpdate.setText(R.string.msg_current_lastest_version_software); } } } @Override protected void onResume() { super.onResume(); SoftwareUpgrade.onResume(); }}
- strings.xml
<string name="msg_init_auto_update_software_failed">初始化自动更新功能失败!</string><string name="msg_current_lastest_version_software">当前为最新版本</string><string name="layout_update_software_update_now">更新(%1$s)</string><string name="layout_update_software_notify">软件升级提醒</string><string name="layout_update_software_update_content">新版特性</string><string name="layout_update_software_not_update">暂不更新</string><string name="msg_no_yyb">未安装应用宝,将开始安装应用宝!</string><string name="msg_has_new_version">软件有新版本,是否更新?</string><string name="msg_waiting_install_yyb">等待安装应用宝</string><string name="msg_download_yyb_success">应用宝下载成功,开始安装应用宝</string><string name="msg_download_yyb_failed">下载应用宝失败,请检查网络连接</string>
接入省流量更新(获取官方介绍)
进入应用
点击基础服务中的
更多
,可进入省流量更新
省流量更新页面中,点击
查看详情
,进入省流量更新详情页