手机卫士-08
手机卫士-08
课1
上一节课:软件管家改善 activityappmanager.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
style="@style/textview_title_style"
android:gravity="center"
android:text="软件管家" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/tv_rom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="剩余手机内部" />
<TextView
android:id="@+id/tv_sd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="sd卡:" />
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/ll_loading"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:visibility="invisible" >
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="玩命加载中...." />
</LinearLayout>
<include layout="@layout/list_view" />
<TextView
android:id="@+id/tv_appsize_lable"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ff888888"
android:text="用户程序:5个"
android:textColor="@android:color/white" />
</FrameLayout>
</LinearLayout>
给显示应用程序和系统程序列表加上可以移动的小条目,我们之前的是固定在第一行,不美观 AppManagerActivity.java 继续完善应用程序条目和系统程序条目的显示 在handler里的listview.setAdapter下方进行控件赋值 但是在老师的软件管家里下滑时第一栏显示的应用程序size还是固定在那里,因此在 AppManagerActivity.java里给listview增加滚动监听事件,当listview滚动到某个位置的时候修改textView
AppManagerActivity.java
/**
* 显示应用程序列表的状态
*/
private TextView tv_appsize_lable;
tv_appsize_lable = (TextView) findViewById(R.id.tv_appsize_lable);
ViewUtils.inject(this);
/**
* 设置listview的一个滚动监听事件
*/
list_view.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 滚动--》静止 --》滚动
}
/**
* 当界面滚动的时候调用的方法
*
* @param firstVisibleItem
* 第一个可见条目的位置
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (userAppInfos != null && systemAppInfos != null) {
//在滑动listView的时候,第一位的位置已经大于等于应用程序的长度+1时,就把在第一个位置的textView改成系统程序的样式和其长度
if (firstVisibleItem >= (userAppInfos.size() + 1)) {
// 用户把界面拖动到下方
tv_appsize_lable.setText("系统程序:"
+ systemAppInfos.size() + "个");
} else {
// 用户把界面拖动到上方
tv_appsize_lable.setText("用户程序:" + userAppInfos.size()
+ "个");
}
}
//当滑动时就关闭弹框窗口
dismissPopupWindow();
}
});
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
// 加载完成之后。隐藏进度条
ll_loading.setVisibility(View.INVISIBLE);
adapter = new AppManagerAdapter(
AppManagerActivity.this, infos);
list_view.setAdapter(adapter);
tv_appsize_lable.setText("用户程序:" + userAppInfos.size() + "个");
};
};
如何实现像微信用户列表的分类显示名字头字母的分类显示。 在activityappmanager.xml里进行调整marginTop
继续实现点击app的条目是实现一些功能,例如卸载等操作
以前是弹出一些dialog,现在使用一些新显示示例。
显示老师在低版本的这种气泡式的显示画面提供功能。 这种小气泡别名叫popup window 弹出窗体 轻量级比dialog,dialog重量级,一般显示在窗体的居中位置。 所以老师的需求就是在每个小条目点击的时候就弹出气泡式窗体。 AppManagerActivity.java 给listview的item条目注册一个点击事件 list_view.setOnItemClickListener
AppManagerActivity.java
// 给listview 的item条目注册一个点击事件
list_view.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
根据position可以把小条目的对象取出来,通过MyAdapter里的getItem去获取对象,所以在listener里配合Adapter的getItem使用获取条目对象。 测试点击listview的时候对象信息拿取完成后,就在listener里使用popupWindow,气泡窗体:PopupWindow popupWindow = new PopupWindow(contentView, 宽,高) 在contentView里放入一个new出来的文本控件对象 然后显示
AppManagerActivity.java
// 准备弹出窗体,指定view和宽高信息
popupWindow = new PopupWindow(contentView, -2, -2);
popupWindow.setBackgroundDrawable(new ColorDrawable(
Color.TRANSPARENT));
// 显示到指定的位置
int[] location = new int[2];
view.getLocationInWindow(location);// 获取了view对象在窗体上的位置
popupWindow.showAtLocation(parent, Gravity.LEFT
+ Gravity.TOP, 50, location[1] - 15);
测试时非常丑,因此修改popupWindow的属性。 PopupWindow.setBackGroundDrawable 效果坑爹,把PopupWindow修改成单例,把其改为类成员变量,一次区分新旧窗体 并做判断:显示悬浮窗体之前,应该判断是否有旧的窗体存在。 isShowing() 继续测试,发现打开了窗体,不点击关闭就一直处在窗体中; 因此我们把窗体关闭封装成方法,然后在listview的滚动监听事件里监听并关闭窗体。
AppManagerActivity.java
private void dismissPopupWindow() {
// 显示悬浮窗体之前,应该判断是否有旧的窗体存在
if (popupWindow != null && popupWindow.isShowing()) {
popupWindow.dismiss();
popupWindow = null;
}
}
课2
继续气泡窗体 新建一个popupappitem.xml,替代之前的textView去填充气泡窗体:PopupWindow popupWindow = new PopupWindow(contentView, 宽,高)
popupappitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/local_popup_bg"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/ll_uninstall"
android:gravity="center_horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="卸载" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_start"
android:gravity="center_horizontal"
android:layout_marginLeft="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img2" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="启动" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_share"
android:gravity="center_horizontal"
android:layout_marginLeft="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img3" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分享" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_detail"
android:gravity="center_horizontal"
android:layout_marginLeft="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img4" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="信息" />
</LinearLayout>
</LinearLayout>
样式
然后进行资源填充。
// 准备一个要显示到界面的view对象
View contentView = View.inflate(AppManagerActivity.this,R.layout.popup_app_item, null);
(暂时效果) 然后注释掉setBackground
老师介绍sdk画图片方法。tools目录-->draw 9-patch--->画图
这样点击后编辑出来的png在android里如果强迫拉伸后也不会变型了。 继续调整窗体的位置、showAtLocation方法里修改
// 显示到指定的位置
int[] location = new int[2];
view.getLocationInWindow(location);// 获取了view对象在窗体上的位置
popupWindow.showAtLocation(parent, Gravity.LEFT
+ Gravity.TOP, 50, location[1] - 15);
+
继续给气泡弹出加上动画效果
加上缩放的动画ScaleAnimation
// 注意:重要细节,动画的播放要求窗体一定有背景颜色。
ScaleAnimation sa = new ScaleAnimation(0.2f, 1.0f, 0.2f,
1.0f, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(300);
contentView.startAnimation(sa);
但是测试时发现动画效果没出来,
原因:没考虑窗体的背景颜色。如果窗体没有背景颜色,那么动画效果显示不出来。 然后尝试取消掉之前注销的背景,然后发现气泡窗体有动画效果了,但是还是很难看。
// 准备弹出窗体,指定view和宽高信息
popupWindow = new PopupWindow(contentView, -2, -2);
popupWindow.setBackgroundDrawable(new ColorDrawable(
Color.TRANSPARENT));
所以把之前的绿色背景改成透明的就ok
继续实现popup里的功能点击事件。(卸载、启动、分享、信息) 在AppManagerActivity里拿到控件的变量。 在点击事件里那到xml里的控件变量。 在每个控件设置点击监听事件。 但是这些监听事件在监听事件里嵌套太深,那么就让本类实现接口。 然后实现点击事件
public class AppManagerActivity extends Activity implements OnClickListener {
ll_start = (LinearLayout) contentView
.findViewById(R.id.ll_start);
ll_detail = (LinearLayout) contentView
.findViewById(R.id.ll_detail);
ll_uninstall = (LinearLayout) contentView
.findViewById(R.id.ll_uninstall);
ll_share = (LinearLayout) contentView
.findViewById(R.id.ll_share);
ll_start.setOnClickListener(AppManagerActivity.this);
ll_detail.setOnClickListener(AppManagerActivity.this);
ll_uninstall.setOnClickListener(AppManagerActivity.this);
ll_share.setOnClickListener(AppManagerActivity.this);
/**
* 界面里面控件的点击事件
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.ll_share:
Log.i(TAG, "分享:" + clickedAppInfo.getAppName());
shareApplication();
break;
case R.id.ll_start:
Log.i(TAG, "启动:" + clickedAppInfo.getAppName());
startApplication();
break;
case R.id.ll_uninstall:
Log.i(TAG, "卸载:" + clickedAppInfo.getAppName());
uninstallApplication();
break;
case R.id.ll_detail:
Log.i(TAG, "详细信息:" + clickedAppInfo.getAppName());
showApplicationDetail();
break;
}
dismissPopupWindow();
}
先实现分享:模板代码(以后使用。),在公司里直接复制粘贴:老师带我们看源码:--->编写短信发给指定人。shareApplication.java在AppManagerActivity.jvava
看系统上层所有应用的源代码包--->mms--->AndroidManifest.xml 把清单文件的部分代码复制到了shareApplication里,对照用意图来编写。
/**
* 分享应用程序
*/
private void shareApplication() {
// <action android:name="android.intent.action.SEND" />
// <category android:name="android.intent.category.DEFAULT" />
// <data android:mimeType="text/plain" />
Intent intent = new Intent();
intent.setAction("android.intent.action.SEND");
intent.addCategory("android.intent.category.DEFAULT");
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT,
"推荐您使用一款软件,名称叫:" + clickedAppInfo.getAppName());
startActivity(intent);
}
使用源代码加意图开启分享功能。(容易)
课3
开发卸载功能:总结成技巧!!! 回顾之前的下载安装APK。 观看源码-->上层源码--->packageInstall-->清单文件--->发现有几个Activity里的intent节点--->我们可以通过这些intent节点去通过意图调用他们 在AppManagerActivity.java里实现卸载应用程序方法uninstallAppliacation() 使用意图调用源代码中的卸载activity,这里注意技巧!! 这种方法以后再编程时想调用系统的应用,就观察系统的源码-->清单文件里观察intent-filter节点,然后使用在代码里用意图调用。 但是发现一个bug,点击卸载后但是listview里还是没有刷新软件被卸载,虽然已经被现在了 所以我们需要使用广播接收者来监听应用的卸载情况,以此来实时更新listview 内部的卸载应用程序的广播接收者 InnerUnInstallReceiver 然后在oncreate里进行注册该内部广播接收者。(注意一定要记得设置广播关心的数据类型:是包被卸载的类型)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_manager);
//初始化注册内部的广播接受者
receiver = new InnerUninstallAppReceiver();
IntentFilter filter = new IntentFilter();
//指定关心 应用程序卸载的广播事件
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
//注意:一定要记得设置 广播关心的数据类型 是包被卸载的类型
filter.addDataScheme("package");
//注册广播接受者
registerReceiver(receiver, filter);
然后在activity里的ondestroy里注销掉内部广播接收者。
@Override
protected void onDestroy() {
//取消内部的广播接受者
unregisterReceiver(receiver);
receiver = null;
super.onDestroy();
}
首先搭建框架--->并测试框架是否成功--->在内部广播框架里输出一些广播接收到的应用卸载的信息:包名
广播框架搭建好了,然后在广播里实现逻辑。(更新listview) 使用for循环去匹配,匹配对了就删去listview里的条目-->并更新 检查是否有报错:报了,数据冲突异常:所以新定义一个对象集合:unInstalledInfo 然后在for里进行迭代,避免了数据冲突异常。 测试成功!程序卸载了动态刷新界面
/**
* 内部的卸载应用程序的广播接受者
*/
private class InnerUninstallAppReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("----------------内部广播接受者,发现卸载了应用"+intent.getData().toString());
//package:com.example.gagaga
AppInfo uninstalledInfo = null;
for(AppInfo info: userAppInfos){
if(("package:"+info.getPackageName()).equals(intent.getData().toString())){
uninstalledInfo = info;
break;
}
}
userAppInfos.remove(uninstalledInfo);
adapter.notifyDataSetChanged();
}
}
开发启动功能:startApplication
每个app里的清单文件的逻辑 发现入口activity必须满足两个条件:1、action为main2、Launcher 如何获取app里的这两个条件?
PackageManager类
/**
* 启动应用程序
*/
private void startApplication() {
PackageManager pm = getPackageManager();
Intent intent = pm.getLaunchIntentForPackage(clickedAppInfo.getPackageName());
if(intent!=null){
startActivity(intent);
}else{
Toast.makeText(this, "无法启动该应用程序", 0).show();
}
}
展示应用信息:调用源码的应用信息界面
从低版本的android系统去打开应用信息界面。 寻找——>点击一个应用的详细信息,发现控制台有打印信息
在上层源码的setting里找到清单文件--->InstallAppDetail--->这就是关键信息 实现展示应用信息的方法:showApplicationDetail() 使用意图去打开! 测试
/**
* 显示应用程序的详细信息
*/
private void showApplicationDetail() {
// <action android:name="android.settings.APPLICATION_DETAILS_SETTINGS" />
// <category android:name="android.intent.category.DEFAULT" />
// <data android:scheme="package" />
Intent intent = new Intent();
intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.addCategory("android.intent.category.DEFAULT");
intent.setData(Uri.parse("package:"+clickedAppInfo.getPackageName()));
startActivity(intent);
}
软件管家的全部功能都实现完了
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。