黑马程序员Android学习笔记——金山卫士项目——第一天

时间:2023-02-19 21:54:50

主要知识点:

1、项目的代码组织结构

2、PackageManager 获取应用程序的版本号;

3、URL HttpUrlConntion

4、子线程 handler + message

5、Json解析

6、Intent  显示意图

7、Alterdialog

8、两种上下文

9、下载--FinalHttp

10、安装apk

11、应用程序的签名;

12、ListView gridView 数据适配

13、滚动的TextView

14、自定义组合控件 实现关闭自动更新;

15、自定义属性

参考文档下载地址:http://download.csdn.net/detail/itjavawfc/8232073

参考源代码下载地址:http://download.csdn.net/detail/itjavawfc/8232083

项目最终运行界面效果:

黑马程序员Android学习笔记——金山卫士项目——第一天

自己第一天主要学习内容总结:

1)启动页面结合设计到检查版本然后判断是否升级【checkUpdate()】:里面根据网络请求通过Message、Handler消息传递机制传递消息,对话框展现是否升级知识,自定义主题实现全屏和4.1以后新的对话框效果,利用系统Intent实习APK安装。

代码如下:

public class SplashActivity extends Activity {
protected static final String TAG = "SplashActivity";
protected static final int ENTR_HOME = 1;
protected static final int SHOW_UPDATE_DIALOG = 0;
protected static final int NETWORK_ERROR = 3;
protected static final int JSON_ERROR =4 ;
protected static final int URL_ERROR = 2;
private TextView tv_splash_version;
private String description;
private TextView tv_update_info;
/*
* 对应新版本的下载地址
*/
private String apkurl;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
sp=getSharedPreferences("config", MODE_PRIVATE);
tv_splash_version=(TextView) findViewById(R.id.tv_splash_version);
tv_splash_version.setText("版本号"+getVersionName());
tv_update_info=(TextView) findViewById(R.id.tv_update_info);
boolean update=sp.getBoolean("dupdate", false);
if(update){
//检查升级
checkUpdate();
}else{
//自动升级已经关闭了
handler.postDelayed(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
enterHome();
}
}, 2000);
}
AlphaAnimation aa=new AlphaAnimation(0.3f, 1.0f);
aa.setDuration(500);
findViewById(R.id.rl_root_splash).startAnimation(aa);
}
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch(msg.what){
case SHOW_UPDATE_DIALOG://显示升级的对话框
Log.i(TAG,"显示升级的对话框");
showUpdateDialot();
break;
case ENTR_HOME: //进入主页面
enterHome();
break;
case URL_ERROR: //URL 错误
enterHome();
Toast.makeText(getApplicationContext(), "URL错误", 0).show();
break;
case NETWORK_ERROR: //网络异常
Toast.makeText(getApplicationContext(), "网络异常", 0).show();
enterHome();
break;
case JSON_ERROR: //JSON解析出错
Toast.makeText(SplashActivity.this, "JSON解析错误", 0).show();
enterHome();
break;
default:
break;
}
}
};

/*
* 检查是否有版本升级,如果有就升级
*/
private void checkUpdate() {

new Thread(){
public void run(){
Message mes=Message.obtain();
long startTime=System.currentTimeMillis();

//URLhttp://192.168.1.105:8080/MobileSafe.apk
try{
URL url=new URL(getString(R.string.serverurl));
//联网
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
int code=conn.getResponseCode();
if(code==200){
//联网成功
InputStream is=conn.getInputStream();
//把流转成String
String result=StreamTools.readFromStream(is);
System.out.println("联网成功");
Log.i(TAG,"联网成功过呢。。"+result);
//json解析
JSONObject obj=new JSONObject(result);
//得到服务器的版本信息
String version=(String) obj.get("verson");
description=(String) obj.get("description");
apkurl=(String) obj.get("apkurl");

//校验是否有新版本
if(getVersionName().equals(version)){
//版本一直,没有新版本,进入主页面
mes.what=ENTR_HOME;

}else{
//有新版本弹出升级对话框
mes.what=SHOW_UPDATE_DIALOG;
}
}
}catch(MalformedURLException e){
mes.what=URL_ERROR;
e.printStackTrace();
} catch (IOException e) {
mes.what=NETWORK_ERROR;
e.printStackTrace();
} catch (JSONException e) {
mes.what=JSON_ERROR;
e.printStackTrace();
}finally{
long endTime=System.currentTimeMillis();
//我们花了多少时间
long dTime=endTime-startTime;
//界面停留2s种
if(dTime<2000){
try {
Thread.sleep(2000-dTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
handler.sendMessage(mes);
}
};
}.start();
}

/*
* 弹出升级对话框
*/
private void showUpdateDialot() {
//this=activity.class
AlertDialog.Builder builder=new Builder(this);
builder.setTitle("提示升级");
//设置此属性,让对话框外的点击事件不可触发
builder.setCancelable(false); //强制升级
//点击返回键时触发
builder.setOnCancelListener(new OnCancelListener(){
@Override
public void onCancel(DialogInterface dialog) {
//进入主页面
enterHome();
dialog.dismiss();
}
});
builder.setMessage(description);
builder.setPositiveButton("立刻升级", new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
//下载APK,bignqie tihuan
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//sd卡存在
FinalHttp finalhttp=new FinalHttp();
finalhttp.download(apkurl, Environment.getExternalStorageDirectory().getAbsolutePath()+"/mobilesafe2.0.apk", new AjaxCallBack<File>(){
@Override
public void onFailure(Throwable t, int errorNo,
String strMsg) {
t.printStackTrace();
Toast.makeText(getApplicationContext(), "下载失败", 1).show();
super.onFailure(t, errorNo, strMsg);
}

@Override
public void onLoading(long count, long current) {
super.onLoading(count, current);
tv_update_info.setVisibility(View.VISIBLE);
//当前下载进度
int progress=(int)(current*100/count);
tv_update_info.setText("下载进度:"+progress+"%");
}

@Override
public void onSuccess(File t) {
// TODO Auto-generated method stub
super.onSuccess(t);
installAPK(t);
}

/*
* 安装APK
*/
private void installAPK(File t) {

Intent intent=new Intent();
intent.setAction("android.intent.action.VIEW");
intent.addCategory("android.intent.category.DEFAULT");
intent.setDataAndType(Uri.fromFile(t), "application/vnd.android.package-archive");
startActivity(intent);
}

});

}else{
Toast.makeText(getApplicationContext(), "没有sdcard,请安装上再试", 0).show();
return ;
}
}

});
builder.setNegativeButton("下次再说", new OnClickListener(){

@Override
public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();//对话框消掉
enterHome();//进入主页面
}
});
builder.show();
}


protected void enterHome() {
Intent intent=new Intent(this,HomeActivity.class);
startActivity(intent);
//关闭当前页面
finish();
}

/*
* 得到应用程序的版本名称
*/
private String getVersionName(){
//用来管理手机的APK
PackageManager pm=getPackageManager();
//得到指定apk的功能的清单文件
try {
PackageInfo info=pm.getPackageInfo(getPackageName(), 0);
return info.versionName;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
}


2)进入主页HomeActivity

复习了GridLayout布局结合Adapter的运用,效果就是上面的图所示,在它的布局文件中学习了一个自定义可滚动的TextView,非常有意思。

public class HomeActivity extends Activity {
private GridView list_home;
private MyAdapter adapter;
private static String[] names={
"手机防盗","通讯卫士","软件管理",
"进程管理","流量统计","手机杀毒",
"缓存清理","高级工具","设置中心"
};
private static int[] ids={
R.drawable.safe,R.drawable.callmsgsafe,R.drawable.app,
R.drawable.taskmanager,R.drawable.netmanager,R.drawable.*,
R.drawable.sysoptimize,R.drawable.atools,R.drawable.settings
};
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
list_home=(GridView) findViewById(R.id.list_home);
adapter=new MyAdapter();
list_home.setAdapter(adapter);
list_home.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
switch(position){
case 8://进入设置中心
Intent intent=new Intent(HomeActivity.this,SettingActivity.class);
startActivity(intent);
break;

default:
break;
}
}
});
}

private class MyAdapter extends BaseAdapter{
//屏幕要显示多少个
@Override
public int getCount() {
// TODO Auto-generated method stub
return names.length;
}

//点击的时候返回某个对象
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view=View.inflate(HomeActivity.this, R.layout.list_item_home, null);
ImageView iv_item=(ImageView) view.findViewById(R.id.iv_item);
TextView tv_item=(TextView) view.findViewById(R.id.tv_item);
tv_item.setText(names[position]);
iv_item.setImageResource(ids[position]);
return view;
}
}
}




<com.example.mobilesafe.ui.FocusedTextView 
android:focusableInTouchMode="true"
android:singleLine="true"
android:ellipsize="marquee"
android:textSize="18sp"
android:text="最新的手机卫士,快来下载,下载就好了"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>


3)在SettingActivity中学习了通过自定义类来自定义布局,SharedPreferences来保存数据,在布局文件中自定义属性。

public class SettingActivity extends Activity {
private SettingItemView siv_update;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
sp=getSharedPreferences("config", MODE_PRIVATE);
siv_update=(SettingItemView) findViewById(R.id.siv_update);
boolean update=sp.getBoolean("update", false);
if(update){
//自动升级已经开启
siv_update.setChecked(true);
}else{
//自动升级已经关闭
siv_update.setChecked(false);
}
siv_update.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Editor editor=sp.edit();
//判断是否选中
//已经打开自动升级
if(siv_update.isChecked()){
siv_update.setChecked(false);
editor.putBoolean("update", false);
}else{
//没有打开自动升级
siv_update.setChecked(true);
editor.putBoolean("update", true);
}
editor.commit();
}
});

}
}