最新实战教程,让你了解Android自动化刷量、作弊与防作弊的那些事,案例:刷友盟统计、批量注册苹果帐号
好啦,我们继续我们昨天的那个项目,昨天我们只完成了一个程序启动时的欢迎界面,但是提到了,启动那个界面时会进行版本的检查,所以今天我们就做那个版本的检查那一块。
既然要做版本检查,那肯定要有服务器啦,所以我们就用到tomcat啦,因为这个项目是Android, 所以我就不写那个服务器端的程序啦,我只用tomcat来进行一个简单的从服务器读取数据,然后更新程序。不会专门写一个服务器端来进行业务的处理。
好,废话不多说,可能有些人还没接触过Web方面的,所以我把tomcat的搭建也简单的说一下,大神可以直接跳到下面去。
首先,我们去tomcat官网上下载一个tomcat 下载地址
在这里选择是32位的还是64位的
下载下来后,安装也很简单,直接解压出来就行啦(前提是你的java环境要正确)
解压好之后,我们就可以去到它的bin目录下面,双击那个startup.bat文件啦
然后我们就会看到一个黑呼呼的界面
然后,我们去浏览器输入 http://localhost:8080/ 然后出现下面的界面,那就说明你的tomcat配置成功了
那么,我们的服务器配置好之后,我们就要用它来为我们的app做一些东西啦
首先,我们在tomcat的webapps目录下载新建一个文件夹叫Security(这个是个人喜欢的,因为我们app叫Security)
update.xml里面的内容
<?xml version="1.0" encoding="utf-8"?>
<update>
<version>1.0</version>
<description>这里写一些这个版本的特点</description>
<apkurl>http://192.168.1.5:8080/Security/new.apk</apkurl>
<!--这里的ip地址一定要写你服务器所在的电脑的ip地址,我们会在Security这个目录下面放置一下new.apk的,用来更新的-->
</update>
好啦,现在测试一下,在浏览器里面输入http://localhost:8080/Security/update.xml 如果能够看到我们刚刚写的update.xml里面的内容,那么,你的服务器就配置成功啦!
先恭喜你,你又会弄服务器啦!!!!!
ps:因为这个要涉及服务器这些知识,所以我们这个app运行的手机上的ip一定要和你运行tomcat那台电脑上的ip是处于同一个局域网的,当时如果有外部ip那就不同,所以最好就是电脑和手机接同一个wifi这个一般会在同一个局域网啦,当然,用模拟器就一定是在同一个局域网啦
好啦,配置好了服务器后,我们就可以继续我们的项目啦,因为要和服务器交互,那么,我们肯定要把交互的地址存起来的啦,所以我们在我们的项目的values目录下新建一个config.xml文件
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="serverUrl">http://192.168.1.5:8080/Security/update.xml</string>
</resources>
好啦,现在,我们的任务是从服务器上读取到update.xml里面的内容,然后再解析它,拿到apk的下载地址,和最新的版本与当时的版本比较嘛,看一下要不要下载,所以我们就要有一个model来存放这些更新的信息了嘛
所以我们就新建一个类com.xiaobin.security.domain.UpdateInfo
package com.xiaobin.security.domain;
public class UpdateInfo
{
private String version;
private String description;
private String url;
public String getVersion()
{
return version;
}
public void setVersion(String version)
{
this.version = version;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
}
然后呢,我们要从服务器上读取到一个update.xml嘛,所以我们也要新建一个类,用来与服务器交互啦
所以新建一个类com.xiaobin.security.engine.UpdateInfoService
package com.xiaobin.security.engine;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.content.Context;
import com.xiaobin.security.domain.UpdateInfo;
public class UpdateInfoService
{
private Context context;
public UpdateInfoService(Context context)
{
this.context = context;
}
public UpdateInfo getUpdateInfo(int urlId) throws Exception
{
String path = context.getResources().getString(urlId);//拿到config.xml里面存放的地址
URL url = new URL(path);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();//开启一个http链接
httpURLConnection.setConnectTimeout(5000);//设置链接的超时时间,现在为5秒
httpURLConnection.setRequestMethod("GET");//设置请求的方式
InputStream is = httpURLConnection.getInputStream();//拿到一个输入流。里面包涵了update.xml的信息
return UpdateInfoParser.getUpdateInfo(is);//解析xml
}
}
刚刚上面那个类里面有一个解析xml的操作,所以我们现在把解析xml的这个类也写一下
所以新建一个类com.xiaobin.security.engine.UpdateInfoParser
package com.xiaobin.security.engine;
import java.io.InputStream;
import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
import com.xiaobin.security.domain.UpdateInfo;
public class UpdateInfoParser
{
public static UpdateInfo getUpdateInfo(InputStream is) throws Exception
{
UpdateInfo info = new UpdateInfo();
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setInput(is, "utf-8");
int type = xmlPullParser.getEventType();
while(type != XmlPullParser.END_DOCUMENT)
{
switch(type)
{
case XmlPullParser.START_TAG :
if(xmlPullParser.getName().equals("version"))
{
info.setVersion(xmlPullParser.nextText());
}
else if(xmlPullParser.getName().equals("description"))
{
info.setDescription(xmlPullParser.nextText());
}
else if(xmlPullParser.getName().equals("apkurl"))
{
info.setUrl(xmlPullParser.nextText());
}
break;
default :
break;
}
type = xmlPullParser.next();
}
return info;
}
}
好啦,现在我们回去给我们昨天写的那个SplashActivity加上一些逻辑啦
package com.xiaobin.security.ui;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.xiaobin.security.R;
import com.xiaobin.security.domain.UpdateInfo;
import com.xiaobin.security.engine.UpdateInfoService;
public class SplashActivity extends Activity
{
private TextView tv_version;
private LinearLayout ll;
private UpdateInfo info;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
tv_version = (TextView) findViewById(R.id.tv_splash_version);
String version = getVersion();
tv_version.setText("版本号 " + version);
ll = (LinearLayout) findViewById(R.id.ll_splash_main);
AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f, 1.0f);
alphaAnimation.setDuration(2000);
ll.startAnimation(alphaAnimation);
if(isNeedUpdate(version))
{
showUpdateDialog();
}
}
private void showUpdateDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setIcon(android.R.drawable.ic_dialog_info);
builder.setTitle("升级提醒");
builder.setMessage(info.getDescription());
builder.setCancelable(false);
builder.setPositiveButton("确定", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// TODO Auto-generated method stub
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
// TODO Auto-generated method stub
}
});
builder.create().show();
}
private boolean isNeedUpdate(String version)
{
UpdateInfoService updateInfoService = new UpdateInfoService(this);
try
{
info = updateInfoService.getUpdateInfo(R.string.serverUrl);
String v = info.getVersion();
if(v.equals(version))
{
System.out.println("不用更新");
return false;
}
else
{
System.out.println("要更新");
return true;
}
}
catch (Exception e)
{
e.printStackTrace();
Toast.makeText(this, "获取更新信息异常,请稍后再试", Toast.LENGTH_SHORT).show();
}
return false;
}
private String getVersion()
{
try
{
PackageManager packageManager = getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0);
return packageInfo.versionName;
}
catch (NameNotFoundException e)
{
e.printStackTrace();
return "版本号未知";
}
}
}
因为我们访问了Internet。所以要在AndroidManifest里面加上权限
<uses-permission android:name="android.permission.INTERNET"/>
好啦,现在可以进行测试一下啦,只要修改update.xml里面的那个version,那样就会提示下载的啦,今天的代码有点多,而且有点乱,所以如果有什么不明白的,或出了什么问题的,都可以留言交流,
最后提示一个,记得要把服务器打开再测试,不然就没效果啦
update:
很多朋友都在这里说不能与服务器交互,其实是这样的,这个一个bug来的,这个bug就是在Android4以上,我们已经不能在主线程里面进行网络操作的啦,如果进行网络操作,就会报错
所以我们就要做一下改动,我们在onCreate方法里面开启一个线程,用来检测更新信息的
new Thread()
{
public void run()
{
try
{
UpdateInfoService updateInfoService = new UpdateInfoService(SplashActivity.this);
info = updateInfoService.getUpdateInfo(R.string.serverUrl);
}
catch (Exception e)
{
e.printStackTrace();
}
};
}.start();
然后呢,就在原来的isNeedUpdate方法里面进行一些修改啦
private boolean isNeedUpdate(String version)
{
if(info == null)
{
Toast.makeText(this, "获取更新信息异常,请稍后再试", Toast.LENGTH_SHORT).show();
loadMainUI();
return false;
}
String v = info.getVersion();
if(v.equals(version))
{
Log.i(TAG, "当前版本:" + version);
Log.i(TAG, "最新版本:" + v);
loadMainUI();
return false;
}
else
{
Log.i(TAG, "需要更新");
return true;
}
}
好啦,到这里,我们的这个bug就修复的啦。在进入今天的内容之前,先谢谢一位网友啦,是他发现这个问题的,非常感谢!
以上这些更新的信息,大家和下一篇文章一起看,就会很清楚的啦,这样子,安装apk也应该可以成功的啦!