一打开电视就显示电视检测到新版本本,而且还点不了升级和忽略

Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!
Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!
Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!
算下来,TomCat服务器已经写了很长一段时间了,一直说拿他来搞点事 情,也一直没做
Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!
算下来,TomCat服务器已经写了很长一段时间了,一直说拿他来搞点事 情,也一直没做,今天刚好有空,交流群还有人请教,就寻思着把一些相关性的原理和基础操作写下来,虽然我网络这一块还是不怎么扎实,嘿嘿,还记得我们怎么搭建的服务器吗?
我们新建一个项目TomCatVersion
这边先来说一下原理,我们做的小例子也是十分的简单,一个首页,我们用Handler实现,然后同步检测当前版本号和系统的版本号对比,如果有升级则弹出提示框提示升级,点击确定开始下载apk,同时显示进度,等下载完成之后启动新下载的APK进行安装,如果点击取消,进入主页,如果没有升级,则直接进入主页,思路应该很清晰吧!那好,我们开始!
一,准备工作
1.搭建TomCat服务器
我们没有服务器,所以使用TomCat服务器模拟,不会搭建的请看
2.新建一个IndexActivity类,并且在AndroidManifest.xml里注册并且设置为主入口
android:name="com.lgl.tomcatversion.IndexActivity" &
android:name="android.intent.action.MAIN" /&
android:name="android.intent.category.LAUNCHER" /&
3.准备一张首页的图片
可有可无,这里作为演示就去网上下载了一张
4.版本更新接口
也就是服务器的地址,我们这里也就直接自己写一段简单的json了
"versionName": "2.0",
"versionCode": 1,
"content": "修复多项bug!",
"url": "http://localhost:192.168.1.101/lgl/TomCatVersion.apk"
我们把他放在服务器里面】
乱码请无视,浏览器的锅
5.网络权限
android:name="android.permission.INTERNET"/&
二.layout_index.xml
布局就没什么内容了,一个进度,一个文本
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/index"
android:gravity="center_horizontal"&
android:gravity="center"
android:layout_alignParentBottom="true"
android:id="@+id/tv_version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:textColor="@android:color/white"
android:textSize="20sp" /&
android:layout_centerInParent="true"
android:layout_alignParentBottom="true"
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp" /&
三.逻辑分析
1.获取版本号
首先你的首页的文本上需要获取当前应用的版本号吧
* 获取APP版本号
private String getAppVersion() {
PackageManager pm = getPackageManager();
packageInfo = pm.getPackageInfo(getPackageName(), 0);
String name = packageInfo.versionN
int version = packageInfo.versionC
Log.i("版本信息", "版本名称:"+name+"版本号"+version);
} catch (NameNotFoundException e) {
e.printStackTrace();
return null;
我们打印出来的Log
我们需要的就是这个name(版本名称)
2.解析JSON
这段json还是十分的简单的,我们直接就用原生的方式解析了,本来想用Volley的,但是演示的话,希望各位自己根据需求使用
* 解析JSON
private void getJSON() {
new Thread() {
public void run() {
HttpURLConnection conn = (HttpURLConnection) new URL(
"http://192.168.1.103:8080/lgl/update.json")
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(3000);
conn.connect();
int responseCode = conn.getResponseCode();
if(responseCode == 200){
InputStream in = conn.getInputStream();
String stream = Utils.toStream(in);
Log.i("JSON", stream);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}.start();
这里我们写了一个Utils来转换流
package com.lgl.
import java.io.ByteArrayOutputS
import java.io.IOE
import java.io.InputS
* 流转换Stream的工具栏
public class Utils {
public static String toStream(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int length = 0;
byte[] buffer = new byte[1024];
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
in.close();
out.close();
return out.toString();
这样我们就可以把Json打印出来了
既然获取到了,那我们就开始解析JSON吧
在Log后面继续写代码
JSONObject jsonObject = new JSONObject(stream);
String versionName = jsonObject.getString("versionName");
int versionCode = jsonObject.getInt("versionCode");
String content = jsonObject.getString("content");
String url = jsonObject.getString("url");
这样我们就解析完成了
3.版本比较以及提示更新
这里我们可以根据name或者code的比较来判断是否有更新,有更新的话,弹出提示框,点确定再更新,我这里就比较Code了,先写以恶搞获取code的方法
* 获取versionCode
private int getCode() {
PackageManager pm = getPackageManager();
packageInfo = pm.getPackageInfo(getPackageName(), 0);
int version = packageInfo.versionC
} catch (NameNotFoundException e) {
e.printStackTrace();
然后我们接着刚才解析完JSON的地方比对,我们先把服务器的JSON数据改了
"versionName": "2.0",
"versionCode": 2,
"content": "修复多项bug!",
"url": "http://192.168.1.103:8080/lgl/TomCatVersion.apk"
这样就会提示更新了,我们检修
if (versionCode & getCode()) {
msg.what = UPDATE_YES;
msg.what = UPDATE_NO;
子线程中我们是不能弹框的,所以我们用Handler,当我们发送UPDATE_YES的时候就弹框,也就是执行我们弹框的方法
* 升级弹框
private void showUpdateDialog() {
updateDialog = new CustomDialog(this, 0, 0, R.layout.dialog_update,
R.style.Theme_dialog, Gravity.CENTER, 0);
dialog_update_content = (TextView) updateDialog
.findViewById(R.id.dialog_update_content);
dialog_update_content.setText(content);
dialog_confrim = (TextView) updateDialog
.findViewById(R.id.dialog_confrim);
dialog_confrim.setOnClickListener(this);
dialog_cancel = (TextView) updateDialog
.findViewById(R.id.dialog_cancel);
dialog_cancel.setOnClickListener(this);
updateDialog.show();
这里我用了一个自定义的Dialog’
CustomDialog
package com.lgl.
import android.app.D
import android.content.C
import android.view.G
import android.view.W
import android.view.WindowM
public class CustomDialog extends Dialog {
public CustomDialog(Context context, int layout, int style) {
this(context, WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT, layout, style,
Gravity.CENTER);
public CustomDialog(Context context, int width, int height, int layout,
int style, int gravity, int anim) {
super(context, style);
setContentView(layout);
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.gravity =
window.setAttributes(params);
window.setWindowAnimations(anim);
public CustomDialog(Context context, int width, int height, int layout,
int style, int gravity) {
this(context, width, height, layout, style, gravity,
R.style.pop_anim_style);
他需要用到一些资源
dialog_update.xml
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="150dip"
android:layout_marginEnd="20dp"
android:layout_marginStart="20dp"
android:background="@drawable/dialog_bg"
android:orientation="vertical" &
android:id="@+id/dialog_notifly_bottom"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom"
android:orientation="horizontal" &
android:id="@+id/dialog_cancel"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:singleLine="true"
android:text="暂不更新"
android:textSize="18sp" /&
android:layout_width="0.2dp"
android:layout_height="match_parent"
android:background="#AAAAAA" /&
android:id="@+id/dialog_confrim"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:singleLine="true"
android:text="立即下载"
android:textSize="18sp" /&
android:id="@+id/dialog_notifly_line"
android:layout_width="match_parent"
android:layout_height="0.2dp"
android:layout_above="@id/dialog_notifly_bottom"
android:background="#AAAAAA" /&
android:id="@+id/dialog_update_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/dialog_notifly_line"
android:layout_below="@+id/TextView01"
android:layout_marginBottom="10dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:gravity="center"
android:singleLine="true"
android:textSize="18sp" /&
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="20dp"
android:gravity="center"
android:singleLine="true"
android:text="检测到有新版本,是否下载?"
android:textSize="18sp" /&
styles.xml
&style name="pop_anim_style"&
&item name="android:windowEnterAnimation"&@anim/pop_in&/item&
&item name="android:windowExitAnimation"&@anim/pop_out&/item&
&style name="Theme_dialog" parent="@android:style/Theme.Dialog"&
&item name="android:windowBackground"&@android:color/transparent&/item&
&item name="android:windowNoTitle"&true&/item&
以及用到的动画
pop_in.xml
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="http://schemas.android.com/apk/res/android" &
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="0"
android:fromYDelta="100%"
android:toXDelta="0"
android:toYDelta="0" /&
pop_out.xml
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="http://schemas.android.com/apk/res/android" &
android:duration="@android:integer/config_shortAnimTime"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="100%" /&
接着我们再执行一下
我们现在再来处理一下没有更新的逻辑,没有更新的话直接跳主页面,我们写一个方法
* 跳转主页面
private void goHome() {
startActivity(new Intent(this, MainActivity.class));
但是这样还是有个问题,他没有更新一下子就跳过去了,所以我们在发消息的时候先让线程睡一会儿
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
handler.sendMessage(msg);
但是这里又出现了一个新的问题,毕竟是网络问题,他是耗时的,这样的话,万一等太久了用户体验也上不去啊,所以我们这里要做一个优化
我们在开始网络请求的时间记录一个时间
long startTime = System.currentTimeMillis();
然后再网络请求结束的时候去计算时间并且计算一共用了多少时间
long endTime = System.currentTimeMillis();
long time = endTime - startT
if (time & 3000) {
Thread.sleep(3000 - time);
} catch (InterruptedException e) {
e.printStackTrace();
4.下载更新以及下载进度
涉及到下载,这里你可以使用很多的开源框架,我这里使用的是xutils
我们下载之后拷贝在libs里就可以用了,用起来也很简单,使用之前先加个权限
android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&
然后开始下载
* 下载更新
private void downloadAPK() {
tv_pro.setVisibility(View.VISIBLE);
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/TomCatVersion.apk";
HttpUtils httpUtils = new HttpUtils();
* 1.网络地址 2.存放地址 3.回调
httpUtils.download(url, path, new RequestCallBack&File&() {
public void onLoading(long total, long current,
boolean isUploading) {
super.onLoading(total, current, isUploading);
tv_pro.setText(100 * current / total + "%");
public void onSuccess(ResponseInfo&File& responseInfo) {
public void onFailure(HttpException error, String msg) {
Log.i("error", msg);
Toast.makeText(getApplicationContext(), "未找到SD卡", Toast.LENGTH_LONG)
这里的代码逻辑也是十分的简单的,多吧,我们来看一下效果‘
更新的包体积有点小,所以一下子就百分之百了,我们去SD卡更目录看一下
确定是下载完成了,但是下完完之后啥也没发生啊,这就要我们再次优化了
下载完之后软起动
下载完之后自动进入安装界面,这才是真正的体验,我们在onSuccess()方法中
// 跳转系统安装页面
Intent i = new Intent()
i.setAction(Intent.ACTION_VIEW)
i.addCategory(Intent.CATEGORY_DEFAULT)
i.setDataAndType(Uri.fromFile(new File(path)),"application/vnd.android.package-archive")
startActivity(i)
我们来看看效果
大致的一个逻辑思路就是这样了
IndexActivity
package com.lgl.
import java.io.F
import java.io.IOE
import java.io.InputS
import java.net.HttpURLC
import java.net.MalformedURLE
import java.net.URL;
import org.json.JSONE
import org.json.JSONO
import android.app.A
import android.content.DialogI
import android.content.DialogInterface.OnCancelL
import android.content.I
import android.content.pm.PackageI
import android.content.pm.PackageM
import android.content.pm.PackageManager.NameNotFoundE
import android.net.U
import android.os.B
import android.os.E
import android.os.H
import android.os.M
import android.util.L
import android.view.G
import android.view.V
import android.view.View.OnClickL
import android.widget.TextV
import android.widget.T
import com.lidroid.xutils.HttpU
import com.lidroid.xutils.exception.HttpE
import com.lidroid.xutils.http.ResponseI
import com.lidroid.xutils.http.callback.RequestCallB
public class IndexActivity extends Activity implements OnClickListener {
private static final int UPDATE_YES = 1;
private static final int UPDATE_NO = 2;
private static final int URL_ERROR = 3;
private static final int IO_ERROR = 4;
private static final int JSON_ERROR = 5;
private TextView tv_
private PackageInfo packageI
private JSONObject jsonO
private String versionN
private int versionC
private TextView tv_
private CustomDialog updateD
private TextView dialog_update_
private TextView dialog_
private TextView dialog_
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_YES:
showUpdateDialog();
case UPDATE_NO:
case URL_ERROR:
Toast.makeText(getApplicationContext(), "地址错误",
Toast.LENGTH_LONG).show();
case IO_ERROR:
Toast.makeText(getApplicationContext(), "请检查网络",
Toast.LENGTH_LONG).show();
case JSON_ERROR:
Toast.makeText(getApplicationContext(), "Json解析错误",
Toast.LENGTH_LONG).show();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_index);
initView();
getJSON();
* 初始化控件
private void initView() {
tv_pro = (TextView) findViewById(R.id.tv_pro);
tv_version = (TextView) findViewById(R.id.tv_version);
tv_version.setText("版本号:" + getAppVersion());
* 获取APP版本号
private String getAppVersion() {
PackageManager pm = getPackageManager();
packageInfo = pm.getPackageInfo(getPackageName(), 0);
String name = packageInfo.versionN
int version = packageInfo.versionC
Log.i("版本信息", "版本名称:" + name + "版本号" + version);
} catch (NameNotFoundException e) {
e.printStackTrace();
return "无法获取";
* 解析JSON
private void getJSON() {
new Thread() {
public void run() {
Message msg = Message.obtain();
long startTime = System.currentTimeMillis();
HttpURLConnection conn = (HttpURLConnection) new URL(
"http://192.168.1.103:8080/lgl/update.json")
.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(3000);
conn.connect();
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
InputStream in = conn.getInputStream();
String stream = Utils.toStream(in);
Log.i("JSON", stream);
jsonObject = new JSONObject(stream);
versionName = jsonObject.getString("versionName");
versionCode = jsonObject.getInt("versionCode");
content = jsonObject.getString("content");
url = jsonObject.getString("url");
if (versionCode & getCode()) {
msg.what = UPDATE_YES;
msg.what = UPDATE_NO;
} catch (MalformedURLException e) {
e.printStackTrace();
msg.what = URL_ERROR;
} catch (IOException e) {
e.printStackTrace();
msg.what = IO_ERROR;
} catch (JSONException e) {
e.printStackTrace();
msg.what = JSON_ERROR;
} finally {
long endTime = System.currentTimeMillis();
long time = endTime - startT
if (time & 3000) {
Thread.sleep(3000 - time);
} catch (InterruptedException e) {
e.printStackTrace();
handler.sendMessage(msg);
}.start();
* 获取versionCode
private int getCode() {
PackageManager pm = getPackageManager();
packageInfo = pm.getPackageInfo(getPackageName(), 0);
int version = packageInfo.versionC
} catch (NameNotFoundException e) {
e.printStackTrace();
* 升级弹框
private void showUpdateDialog() {
updateDialog = new CustomDialog(this, 0, 0, R.layout.dialog_update,
R.style.Theme_dialog, Gravity.CENTER, 0);
updateDialog.setOnCancelListener(new OnCancelListener() {
public void onCancel(DialogInterface dialog) {
dialog_update_content = (TextView) updateDialog
.findViewById(R.id.dialog_update_content);
dialog_update_content.setText(content);
dialog_confrim = (TextView) updateDialog
.findViewById(R.id.dialog_confrim);
dialog_confrim.setOnClickListener(this);
dialog_cancel = (TextView) updateDialog
.findViewById(R.id.dialog_cancel);
dialog_cancel.setOnClickListener(this);
updateDialog.show();
* 点击事件
public void onClick(View v) {
switch (v.getId()) {
case R.id.dialog_confrim:
updateDialog.dismiss();
downloadAPK();
case R.id.dialog_cancel:
* 跳转主页面
private void goHome() {
startActivity(new Intent(this, MainActivity.class));
* 下载更新
private void downloadAPK() {
tv_pro.setVisibility(View.VISIBLE);
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
path = Environment.getExternalStorageDirectory().getAbsolutePath()
+ "/TomCatVersion.apk";
HttpUtils httpUtils = new HttpUtils();
* 1.网络地址 2.存放地址 3.回调
httpUtils.download(url, path, new RequestCallBack&File&() {
public void onLoading(long total, long current,
boolean isUploading) {
super.onLoading(total, current, isUploading);
tv_pro.setText(100 * current / total + "%");
public void onSuccess(ResponseInfo&File& responseInfo) {
Intent i = new Intent();
i.setAction(Intent.ACTION_VIEW);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setDataAndType(Uri.fromFile(new File(path)),
"application/vnd.android.package-archive");
startActivity(i);
public void onFailure(HttpException error, String msg) {
Log.i("error", msg);
Toast.makeText(getApplicationContext(), "未找到SD卡", Toast.LENGTH_LONG)
layout_index.xml
&?xml version="1.0" encoding="utf-8"?&
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/index"
android:gravity="center_horizontal" &
android:id="@+id/tv_version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:gravity="center"
android:textColor="@android:color/white"
android:textSize="20sp" /&
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerInParent="true"
android:layout_marginBottom="60dp" /&
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginTop="207dp"
android:gravity="center"
android:text="欢迎"
android:textColor="#fff"
android:textSize="50sp" /&
android:textColor="#220000"
android:visibility="invisible"
android:id="@+id/tv_pro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/progressBar"
android:layout_centerHorizontal="true"
android:layout_marginBottom="95dp"
android:textAppearance="?android:attr/textAppearanceLarge" /&
Demo下载地址:
用云栖社区APP,舒服~
【云栖快讯】诚邀你用自己的技术能力来用心回答每一个问题,通过回答传承技术知识、经验、心得,问答专家期待你加入!&&
服务底层使用经国家密码管理局检测认证的硬件密码机,通过虚拟化技术,帮助用户满足数据安全方面的...
基于深度学习技术及阿里巴巴多年的海量数据支撑, 提供多样化的内容识别服务,能有效帮助用户降低...
通过在客户自己的数据中心内交付完整的阿里云软件堆栈,阿里云专有云帮助政企客户向混合云架构平滑...
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效...
阿里云总监课正式启航智能电视机屏幕上出现检测到新版本怎么去除
按时间排序
你可以去电视的设置或者升级里面,找到自动升级提醒,关闭就可以了,如果你还有问题,可以到酷开社区专门版块看看,找找智能电视相关信息,有一些教程可能对你有帮助。
那是系统提示你要升级如果不想升级按返回键就行了
升级一下就OK啦,像我买的微鲸智能电视每个月都是有版本升级的,升级是好事,可以有新功能还优化系统。
感谢您为社区的和谐贡献力量请选择举报类型
经过核实后将会做出处理感谢您为社区和谐做出贡献
确定要取消此次报名,退出该活动?
请输入私信内容:

我要回帖

更多关于 创维电视检测到新版本 的文章

 

随机推荐