61_ 短信备份的原理_30

1、查看金山手机卫士的短信备份功能。

短信备份的原理,是用内容提供者读取短信,然后保存。

2、在高级工具AtoolsActivity布局文件里添加短信备份,并处理点击事件smsBackup

3、在com.itheima.mobilesafe.utils工具包目录创建工具类SmsTools用于写短信备份代码

A:短信备份方法backup(Context context,String path)

B:导出短信数据库保存的路径

data/data/com.android.provider.telephony/databases/mmssms.db

address 短信收件人发件人地址

date 短信接收的时间

type 1 发进来短信 2 发出去短信

read 1已读短信 0 未读短信

C:参照源代码Uri路径怎么写

//备份所有的短信,未读的、已读的等待

Uri uri = Uri.parse("content://sms/");

读取短信代码:

Cursor cursor = resolver.query(uri, new String[]{"address","date","type","body"}, null, null, null);

while(cursor.moveToNext()){

String address = cursor.getString(0);

String date = cursor.getString(1);

String type = cursor.getString(2);

String body = cursor.getString(3);

}

把短信生成XML文件,得到xml的序列化器,设置参数

XmlSerializer serializer = Xml.newSerializer();

File file = new File(path);

FileOutputStream os = new FileOutputStream(file);

//设置序列化器的参数

serializer.setOutput(os, "utf-8");

设置文档的开头和结束

serializer.startDocument("utf-8", true);

serializer.endDocument();

设置文档根节点smss开始和结束

serializer.startTag(null, "smss");

serializer.endTag("", "smss");

设置sms里面具体内容,在while循环里面做

serializer.startTag(null, "sms");

serializer.startTag(null, "address");

String address = cursor.getString(0);

serializer.text(address);

serializer.endTag(null, "address");

serializer.endTag(null, "sms");

4、使用写好的短信备份工具

判断sdcard是否存在

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath(),"smsbackup.xml");

try {

SmsTools.backup(this, file.toString());

Toast.makeText(this, "短信备份成功", 0).show();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

Toast.makeText(this, "短信备份失败", 0).show();

}

}else{

Toast.makeText(this, "sdcard不可用", 0).show();

return;

}

5、添加读短信的权限

<uses-permission ndroid:name="android.permission.READ_SMS" />

知识拓展 生成excel表 poc

http://blog.csdn.net/zhy_cheng/article/details/10286563

62_接口和回调_26

1、当前备份短信代码,是写在主线程,如果短信很多的话会出现ANR异常。

2、把短信备份代码移植到子线程;

new Thread(){

public void run() {

try {

SmsTools.backup(AtoolsActivity.this, file.toString());

} catch (Exception e) {

e.printStackTrace();

}

};

}.start();

3、模拟短信备份耗时,在没一个While循环里休眠1000毫秒

4、创建一个对话框ProgressDialog用户等待备份时间,和消掉对话框

显示对话框

final ProgressDialog dialog = new ProgressDialog(this);

dialog.setMessage("请稍等,正在备份钟...");

dialog.show();

备份完后在子线程消掉对话框?

dialog.dismiss();

运行演示,看效果;

5、做成是有加载进度的对话框

dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

但是我们需要知道总条数和当前备份了多少条;

运行演示看效果

在短信备份方法增加参数ProgressDialog dialog参数

在备份方法里设置短信总条数

//设置总条数

dialog.setMax(cursor.getCount());

定义进度

//当前进度

int progress = 0;

在while循环里跟新进度

progress ++;

dialog.setProgress(progress);

考虑在工作中真实的情况:

备份短信界面 UI  是由A程序员写的;

备份短信的功能工具类  是用B程序员写的;

A程序员被老板叫去需要改成进度条,在布局文件修改

<ProgressBar

android:id="@+id/progressBar1"

style="?android:attr/progressBarStyleHorizontal"

android:layout_width="fill_parent"

android:layout_height="wrap_content" />

在代码里初始化

(ProgressBar) findViewById(R.id.progressBar1);

并找程序员B帮忙吧参数修改成ProgressBar

这时候程序员A又被老板叫去说,还没有原来的好看,改成原来的吧;如果有版本控制工具,可以还原,但同时也还原了B程序员的代码;

这时候老板又突发奇想,说想要对话框同时显示进度条

A程序员就需要把注释的地方打开,然后需要B程序员再增加一个参数ProgressDialog ,B程序员还需要做如下代码:

progressDialog.setMax(cursor.getCount());

在while循环里还得progressDialog.setProgress(progress);

给我暴露一个接口吧

给我提供一个回调

6、接口的定义

B工程师最关心的是备份的过程,并不关心如何更新UI;

但B工程师知道在相应时间更新需要跟新对应UI;

B工程师定义一个接口。暴露一些回调;

// B 工程师就定义一个接口,暴露一些回调方法;

public interface SmsBackupCallBack {

/**

* 当短信备份前调用的方法

* @param total 短信的总条数

*/

public void beforeSmsBackup(int total);

/**

* 当短信备份过程中调用

* @param progress 备份的进度

*/

public void onSmsBackup(int progress);

}

备份方法参数和里面的变化

backup(Context context, String path, SmsBackupCallBack backupCallBack)

当短信备份前调用的方法

backupCallBack.beforeSmsBackup(cursor.getCount());

While循环里面的代码

backupCallBack.onSmsBackup(progress);

7、回调的使用

new SmsBackupCallBack() {

@Override

public void onSmsBackup(int progress) {

dialog.setProgress(progress);

progressBar1.setProgress(progress);

}

@Override

public void beforeSmsBackup(int total) {

dialog.setMax(total);

progressBar1.setMax(total);

}

}

A程序员有接到任务了,把进度掉去掉就行了,这样就很方便了;

63_获取手机存储空间信息_22

1、要开发软件管理这个功能了,启动2.3模拟题,参照金山手机卫士看一下;

2、创建AppManagerActivity并在功能清单文件注册,验证完成跳转逻辑;

3、参照金山手机卫士,写相对布局,用于保存

<RelativeLayout

android:layout_width="fill_parent"

android:layout_height="wrap_content" >

<TextView

android:id="@+id/tv_avail_rom"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="3dip"

android:text="内存可用:"

android:textColor="#000000"

android:textSize="16sp" />

<TextView

android:id="@+id/tv_avail_sd"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_marginRight="3dip"

android:text="sd卡可用:"

android:textColor="#000000"

android:textSize="16sp" />

</RelativeLayout>

这里说的内存和电脑说的内存是有区别的,这里的内存指的是手机内部存储空间,相当于手机内置了一块硬盘;

4、获取某个路径可用的空间的大小

public long getTotalSpace(String path){

StatFs statfs = new StatFs(path);

//得到有多少个可以使用

int count =statfs.getAvailableBlocks();

//得到每一个的容量

int size = statfs.getBlockSize();

return count*size;

}

解释为什么要相乘

在左面上创建一个空文件连续写4个a一边写一遍看

画图进一步分析

5、修改getTotalSpace()方法直接返回计算好的结构

/**

* 获取某一个路径的可用空间的总大小

* @param path

* @return

*/

public String getTotalSpace(String path){

StatFs statfs = new StatFs(path);

//得到一个可以用的区域的大小

int count =statfs.getAvailableBlocks();

//得到一个可以用的区域的个数

int size = statfs.getBlockSize();

return Formatter.formatFileSize(this, count*size);

}

Formatter的包是: android.text.format

高端手机内存比较大,int类型无法容纳,需要改成long类型

原理:int 最大值2147483647

2147483647/1024 = 2097151.999023438 KB

2097151.999023438/1024 = 2047.999999046326 MB;

2047.999999046326/1024 = 1.999999999068677 GB

支持2G左右的大小数据,多余的就溢出了

public String getTotalSpace(String path){

StatFs statfs = new StatFs(path);

long count =statfs.getAvailableBlocks();

long size = statfs.getBlockSize();

return Formatter.formatFileSize(this, count*size);

}

64_获取手机里面应用程序信息_20

1、Android的应用程序安装在哪里呀?

pc电脑默认安装在C:\Program Files

Android 的应用安装在哪里呢,如果是用户程序,安装在data/app/目录下

安装Android软件 做两件事

A:把APK拷贝到data/app/目录下

B:把安装包信息写到data/system/目录下两个文件packages.list 和 packages

2、安装包信息在data/system/

Packages.list 里面的0 表示系统应用 1 表示用户应用

Packages.xml是存放应用的一些权限信息的;

系统带应用安装在system/app/目录下

3、用PackageManger得到应用的信息;

A、创建新包com.itheima.mobilesafe.engine 里面创建新类AppInfoProvider

B、在AppInfoProvider里面创建方法public List<AppInfo> getAppInfos()

C、创建实体类AppInfo,并实现set和get方法

private Drawable icon;

private String name;

private String packageName;

private boolean isRom;

4、部分代码的实现

PackageManager pm = context.getPackageManager();

List<PackageInfo> infos = pm.getInstalledPackages(0);

for(PackageInfo info : infos){

AppInfo appinfo = new AppInfo();

String packageName = info.packageName;

Drawable icon = info.applicationInfo.loadIcon(pm);

String name = info.applicationInfo.loadLabel(pm).toString();

appinfo.setIcon(icon);

appinfo.setName(name);

appinfo.setPackageName(packageName);

appinfos.add(appinfo);

}

5、写测试代码测试com.ithiema.mobilesafe.test

public class TestAppInfoProvider extends AndroidTestCase {

public void testgetAppInfos(){

List<AppInfo> appinfos = AppInfoProvider.getAppInfos(getContext());

for(int i = 0; i < appinfos.size();i++){

AppInfo info =  appinfos.get(i);

System.out.println(info.toString());

}

}

}

6、为看方便打印,重新toString()方法

65_程序管理器的UI显示_43

1、获取应用程序类型,是用户应用还是系统应用

在AppInfo 实体类增加 boolean isUuserApp 并创建set和get方法

info.applicationInfo.flags;

//flags是应用程序的特征标志。可以是任意标志的组合 。

一个int在内存中占4个字节,一个字节占8个二进制位,所以一个int在内存中表示32位。

画图分析理解flags

最多可以移位31位,因为总共有32位;这样设计的目的是什么呢?

看看生活中的案例--机读卡看图片

答题卡 英语答题卡 参照机读卡思路和原理我们开发一个机读系统

举例生活中的例子,老师手工改试卷

如何知道是系统应用还是用户应用的,画图理解

写具体代码了---判断是系统应用还是用户应用

if((flas & ApplicationInfo.FLAG_SYSTEM)==0){

//用户应用

}else{

//系统应用

}

判断是按照在内存里还是外部存储里面

if((flas & ApplicationInfo.FLAG_EXTERNAL_STORAGE)==0){

//手机内存

}else{

//外部存储

}

与运算比if else 判断效率高一些

赋值测试运行;

2、布局文件写上ListView ,并加上加载效果

<FrameLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

<ListView

android:id="@+id/ll_app_manager"

android:layout_width="fill_parent"

android:layout_height="fill_parent" >

</ListView>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:gravity="center"

android:orientation="vertical" >

<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>

</FrameLayout>

3.初始化ListView和加载效果线性布局并加载数据

A:在onCreate()方法里,子线程加载数据

new Thread(){

public void run() {

infos =  AppInfoProvider.getAppInfos(AppManagerActivity.this);

handler.sendEmptyMessage(0);

};

}.start();

刷新界面用handler

private Handler handler = new Handler(){

public void handleMessage(android.os.Message msg) {

adapter = new MyAppAdapter();

ll_app_manager.setAdapter(adapter);

};

};

B:自定义Adapter,并把数据传进数据,自定义每条的布局list_app_item.xml;布局文件模仿金山手机卫士部分功能

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="60dip" >

<ImageView

android:id="@+id/iv_icon"

android:layout_width="50dip"

android:layout_height="50dip"

android:layout_marginLeft="5dip"

android:layout_marginTop="5dip"

android:src="@drawable/app" />

<TextView

android:id="@+id/tv_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="6dip"

android:layout_toRightOf="@id/iv_icon"

android:text="程序名称"

android:textColor="#000000"

android:textSize="20sp" />

<TextView

android:id="@+id/tv_location"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="3dip"

android:layout_toRightOf="@id/iv_icon"

android:layout_below="@id/tv_name"

android:text="安装位置"

android:textColor="#88000000"

android:textSize="14sp" />

</RelativeLayout>

代码实现getView()里:

View view = null;

ViewHolder holder;

if(convertView != null){

view = convertView ;

holder = (ViewHolder) view.getTag();

}else{

view =View.inflate(AppManagerActivity.this, R.layout.list_app_item, null);

holder = new ViewHolder();

holder.iv_icon = (ImageView) view.findViewById(R.id.iv_icon);

holder.tv_name = (TextView) view.findViewById(R.id.tv_name);

holder.tv_location = (TextView) view.findViewById(R.id.tv_location);

view.setTag(holder);

}

AppInfo info = infos.get(position);

holder.iv_icon.setImageDrawable(info.getIcon());

holder.tv_name.setText(info.getName());

if(info.isRom()){

holder.tv_location.setText("手机内存");

}else{

holder.tv_location.setText("外部存储");

}

4、设置指定应用安装在手机内存中还是外部存储卡中

在功能清单根节点处添加

android:installLocation="auto"

auto:自动安装,优先安装在手机内存里面 ,可以切换;

internalOnly:只安装在手机内存里面,不可以切换;

preferExternal:安装在外包存储,可以选切换;

66_复杂的ListView的显示_29

1、把系统应用和用户应用区分开来

定义两个集合

List<AppInfo> userInfos; 、List<AppInfos> systemInfos;

初始化数据,用for区分开来

userInfos = new ArrayList<AppInfo>();

systemInfos = new ArrayList<AppInfo>();

for(AppInfo info : infos){

if(info.isUserApp()){

//用户应用

userInfos.add(info);

}else{

//系统应用

systemInfos.add(info);

}

}

2、 在适配器 getCount()方法里重写成如下;

public int getCount() {

return userInfos.size()+systemInfos.size();

}

在适配器的getView()方法如何修改呢?

画图分析

3、代码实现

AppInfo info = null;

if(position < userInfos.size()){

//加载用户程序

info = userInfos.get(position);

}else{

//加载系统程序

//系统的0

int newposition = position -userInfos.size() ;

info = systemInfos.get(newposition);

}

系统应用和用户应用的区别,系统的没法卸载,用户程序可以卸载

4、修改适配器增加 用户程序 和 系统程序 条目

A:在适配器getCount()方法里修改

public int getCount() {

//多了两个TextView的item 所以 +1  +1

return userInfos.size()+1+systemInfos.size()+1;

}

B:在getView()方法里修改

getView的作用:是控制每个位置显示的内容

添加用户程序的TextView

if(position == 0){//创建一个TextView显示多少个用户程序

TextView view = new TextView(AppManagerActivity.this);

view.setText("用户程序("+userInfos.size()+")");

view.setTextColor(Color.WHITE);

view.setBackgroundColor(Color.GRAY);

return view;

}

添加系统程序的TextView

else if(position == userInfos.size() +1 ){

TextView view = new TextView(AppManagerActivity.this);

view.setText("系统程序("+systemInfos.size()+")");

view.setTextColor(Color.WHITE);

view.setBackgroundColor(Color.GRAY);

return view;

}

特殊情况处理了,需要处理一般情况了,画图分析

用户程序显示

else if(position <= userInfos.size()){

//用户程序

int newposition = position -1;

info = userInfos.get(newposition);

}

系统程序显示

else{

//系统程序

int newposition = position -1- userInfos.size()  - 1;

info = systemInfos.get(newposition);

}

运行拖动演示报错,讲解报错的原因

删除应用 ,进入应用管理 ,删除应用 进入应用管理

contverView

重用旧的视图,如果可能的话。注意:您应该检查,这个观点是在使用非空和适当的类型。如果它是不可能将这个视图来显示正确的数据,这种方法可以创建一个新的视图。异构列表可以指定数量的视图类型,以便这一观点总是正确的类型(见getViewTypeCount()和getItemViewType(int))。

5、解决报错问题

if(convertView!=null&&convertView instanceof RelativeLayout){

//.................

}else{

//.............

}

6、回顾处理ListView 中的getCount()和getView()这个过程

67_ListView的状态栏_14

知识拓展,增加快速滚动条

在ListView布局文件加上:

android:fastScrollEnabled="true"

1、在布局文件添加TextView长得和getView里面创建的一样

<TextView

android:textColor="#ffffff"

android:background="#ff888888"

android:text="用户程序(7)"

android:layout_width="fill_parent"

android:layout_height="wrap_content" />

2.给ListView设置滚动监听

ll_app_manager.setOnScrollListener(new OnScrollListener() {

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

if(systemInfos != null&&userInfos != null){

if(firstVisibleItem > userInfos.size()){

//显示系统应用

tv_status.setText("系统程序("+systemInfos.size()+")");

}else{

//显示用户应用

tv_status.setText("用户程序("+userInfos.size()+")");

}

}

}

});

68_popupwindow的使用_44

1、打开2.3模拟器演示联系人效果

2、创建一个新工程专门学习popupwindow

一个弹出窗口,可以用来显示一个任意视图。弹出窗口是一个浮动的容器,出现在当前活动的顶端。

在按钮中添加点击事件

初识popupWindow

TextView contentView = new TextView(this);

contentView.setText("我是PopupWindow");

contentView.setTextColor(Color.RED);

View parent = findViewById(R.id.rl_root);

PopupWindow window = new PopupWindow(contentView, 200, 100);

window.showAtLocation(parent, Gravity.LEFT + Gravity.TOP, 200, 100);

左上角对齐

通过设置PopupWindow 的背景,了解它有多大

PopupWindow window = new PopupWindow(contentView, 200, 100);

window.setBackgroundDrawable(new ColorDrawable(Color.GREEN));

window.showAtLocation(parent, Gravity.LEFT + Gravity.TOP, 200, 100);

点击返回直接退出Activity

对话框点击退出是消掉,那么PopupWindow是否也可以呢?

PopupWindow window = new PopupWindow(contentView, 200, 100,true);

3、把学习好的PopupWindow 移植到工程中

A:监听每点一条的事件,并打印日志;

Object obj = ll_app_manager.getItemAtPosition(position);

System.out.println("obj=="+obj);

getItemAtPosition(position): 获取数据列表中指定的位置。

B:在适配器中修改如下,运行点击,看日志

public Object getItem(int position) {

return "asbllldkk";

}

解决该问题:

@Override

public Object getItem(int position) {

AppInfo info = null;

if(position == 0){//创建一个TextView显示多少个用户程序

return null;

}else if(position == userInfos.size() +1 ){

return null;

}else if(position <= userInfos.size()){

//用户程序

int newposition = position -1;

info = userInfos.get(newposition);

}else{

//系统程序

int newposition = position -1- userInfos.size()  - 1;

info = systemInfos.get(newposition);

}

return info;

}

点击事件做处理,运行看日志

Object obj = ll_app_manager.getItemAtPosition(position);

if(obj != null){

AppInfo info = (AppInfo) obj;

System.out.println("info=="+info.getPackageName());

}

4、在点击事件中添加PopuWindow,运行演示,并点击看效果

TextView contentView = new TextView(AppManagerActivity.this);

contentView.setText(info.getPackageName());

contentView.setTextColor(Color.RED);

PopupWindow popupWindow = new PopupWindow(contentView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

int [] location = new int[2];

view.getLocationInWindow(location);

popupWindow.showAtLocation(parent, Gravity.LEFT+Gravity.TOP, 0, location[1]);

5、希望同一时间只能显示一个PopupWindow

把PopWindow定义成类的成员变量

每次点击,隐藏上次创建的,便于重新创建

if(popupWindow != null&&popupWindow.isShowing()){

popupWindow.dismiss();

popupWindow = null;

}

6、滚动时隐藏PopupWindow

把隐藏PopupWindow代码重构成一个方法dimissPopupWindow();

在监听滚动处onScroll()和点击前调用即可;

7、自定义布局文件加载到PopupWindow里;

我们希望,弹出的PopupWindow有三个功能,启动软件 卸载软件 分享软件

自定义线性布局文件popup_item.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: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="卸载"

android:textColor="#000000" />

</LinearLayout>

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="5dip"

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="启动"

android:textColor="#000000" />

</LinearLayout>

<LinearLayout

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="5dip"

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="分享"

android:textColor="#000000" />

</LinearLayout>

</LinearLayout>

把布局文件加载到PopupWindow里面

把TextView 注释掉,加载如下代码

View contentView = View.inflate(getApplicationContext(), R.layout.popup_item, null)

运行演示看效果,修改距离左边 60个像数;

解决图片竖直方法不协调文,把图片local_popup_bg移动到drawable-hdpi目录,运行,并解释现象;

当前模拟器屏幕是480*800,当前引用的图片drawable-hdpi目录下图片,最适合他,如果找不到就会到drawbale目录下去找,drawbale是所有屏幕默认使用的图片,它没有对图片做缩放处理;图片是多大就显示多大;drawable-xxhdpi目录下图片是给超大手机屏幕使用的,如果在其他目录没有找到图片,它就到drawable-xxhdpi去找,本身图片就很大,显示的时候做缩小显示。当热缩小也是不会很小。

开发过程中,一般会有两套以上图片

8、给PopupWindow加上两个动画效果

AlphaAnimation aa = new AlphaAnimation(0.5f, 1.0f);

aa.setDuration(500);

ScaleAnimation sa = new ScaleAnimation(0.5f, 1.0f, 0.5f,

1.0f, Animation.RELATIVE_TO_SELF, 0,

Animation.RELATIVE_TO_SELF, 0.5f);

sa.setDuration(500);

AnimationSet set = new AnimationSet(false);

set.addAnimation(sa);

set.addAnimation(aa);

//播放动画

contentView.startAnimation(set);

演示当时间设置5秒也没用效果,原因是PopupWindow没有加背景;

播放动画是要前提:就是窗体必须有背景;为什么呢?

如果没有背景的话,就不知道以怎么样的方式画出来,没有办法去合成背景颜色。

9、要想有动画效果就需要设置背景,透明背景也行

popupWindow = new PopupWindow(contentView,

LayoutParams.WRAP_CONTENT,

LayoutParams.WRAP_CONTENT);

//必须要设置背景

popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));

注意:需要在构造方法后面这张背景,在

popupWindow.showAtLocation(parent, Gravity.LEFT

+ Gravity.TOP, 60, location[1]);

后面才设置背景同样也是没有效果的。

69_软件管理器的完成_39

1、定义ID处理点击事件ll_uninstall 、ll_start、ll_share

在线性布局加上ID,初始化成类的成员变量。

private LinearLayout ll_uninstall;

private LinearLayout ll_start;

private LinearLayout ll_share;

在Activity设置点击事件

ll_uninstall.setOnClickListener(AppManagerActivity.this);

ll_start.setOnClickListener(AppManagerActivity.this);

ll_share.setOnClickListener(AppManagerActivity.this);

AppInfo 也定义成类的成员变量,并写注释;

private AppInfo info ;

处理点击事件,打日志,点击并把PopupWindow消掉

@Override

public void onClick(View v) {

dimissPopupWindow();

switch (v.getId()) {

case R.id.ll_uninstall:

Log.i(TAG, "卸载:"+info.getName());

break;

case R.id.ll_share:

Log.i(TAG, "分享:"+info.getName());

break;

case R.id.ll_start:

Log.i(TAG, "启动:"+info.getName());

break;

}

}

2、卸载程序

Intent intent = new Intent();

intent.setAction("android.intent.action.VIEW");

intent.addCategory("android.intent.category.DEFAULT");

intent.setData(Uri.parse("package:"+info.getPackageName()));

startActivity(intent);

卸载后刷新界面

启动Intent 改成

startActivityForResult(intent, 0);

把刷得到数据,并刷新界面的代码重构到fillData()方法里面

在onActivityResult();调用fillData方法,代码如下:

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

fillData();

}

卸载系统应用加上判断

if(info.isUserApp()){

}else{

Toast.makeText(this, "系统应用需要root权限后才能卸载", 0).show();

}

3、软件的分享

进入金山软件主页,按菜单键。点击推荐

金山的包名:com.ijinshan.mguard

QQ的包名:com.tencent.mobileqq

写代码是参照短信应用去写Action

/**

* 分享应用

*/

private void shareApp() {

Intent intent = new Intent();

//<action android:name="android.intent.action.SEND" />

//<category android:name="android.intent.category.DEFAULT" />

//  <data android:mimeType="text/plain" />

intent.setAction("android.intent.action.SEND");

intent.addCategory("android.intent.category.DEFAULT");

intent.setType("text/plain");

intent.putExtra(Intent.EXTRA_TEXT, "推荐一款软件名叫:"+info.getName()+",下载地址:ccc"+info.getPackageName());

startActivity(intent) ;

}

https://play.google.com/store/apps/details?id=com.tencent.mobileqq

知识拓展,当前的代码已经支持分享到QQ空间里面了;

详情:

Intent intent = new Intent();

intent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");

intent.addCategory(Intent.CATEGORY_DEFAULT);

intent.setData(Uri.parse("package:" + clickedAppInfo.getPackname()));

startActivity(intent);

4、软件的启动,打开应用程序的Activity

启动原理,开启Activity ,第一个Activity是通常是启动类;

private void startApp() {

Intent intent = new Intent();

PackageManager pm = getPackageManager();

try {

PackageInfo packInfo = pm.getPackageInfo(info.getPackageName(), 0);

ActivityInfo [] acivityInfos = packInfo.activities;

if(acivityInfos != null&&acivityInfos.length>0){

ActivityInfo activityInfo = acivityInfos[0];

intent.setClassName(info.getPackageName(), activityInfo.name);

startActivity(intent);

}else{

Toast.makeText(this, "这个程序没有界面", 0).show();

}

} catch (NameNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

Toast.makeText(this, "这个应用无法启动", 0).show();

}

}

解决弹出没有界面的问题,分析问题的原因

PackageInfo packInfo = pm.getPackageInfo(info.getPackageName(),PackageManager.GET_ACTIVITIES);

演示启动各个软件,启动联系人 Pico TTS启动报错 ,金山屏蔽了

模仿360安全卫士项目笔记7相关推荐

  1. 模仿360安全卫士项目笔记9

    82_程序锁的UI_48 1.参照腾讯手机管家,看一看演示软件锁功能:设置密码,启动软件试试: 2.在高级工具里面添加"程序锁"enterApplock,添加点击事件. 3.创建新 ...

  2. 模仿360安全卫士项目笔记8

    72_得到手机的内存ram信息_41 1.参照金山手机卫士的进程管理 2.创建TaskManagerActvity并在功能清单文件注册. 布局文件基于软件管理界面修改一下.并且修改对应的文字和ID: ...

  3. 模仿360安全卫士项目笔记10

    92_杀毒软件的原理_34 1.什么是病毒? 电脑上的一个特殊的程序: 2.计算机第一个病毒? 搜索:计算机第一个病毒: 当时人们只是为了研究某个技术是否可行.没事干的时候开发的. 目的:技术研究或者 ...

  4. 模仿360安全卫士项目笔记1

    01_项目介绍_20 演示项目功能: 1.对前面知识的综合应用,复习基础一遍. 2.熟悉代码,找到敲代码的感觉: 3.每天会有1000-1500行代码量:这几天下来一共就会有1万多行代码量. 4.大学 ...

  5. 模仿360安全卫士项目笔记5

    42_自定义土司显示归属地_26 演示:目前的土司的缺陷,比如:无法控制消失.界面丑 1.看Toast的源代码 2.查看toast布局文件的背景目录:\sdk\platforms\android-16 ...

  6. 模仿360安全卫士项目笔记3

    27_手机防盗的原理_30 手机防盗的前提就是绑定sim,如果不绑定没意义: 1.在Setup2Activity页面时,当点击下一个按钮是校验是否设置了sim绑定,没绑定的话不让进入: 2.在Sele ...

  7. 模仿360安全卫士项目笔记4

    39_抖动和振动效果_32 1.进入模拟器的APIDemo展示点击输入框振动效果(views/animation/shake): //shake 动摇:摇动:震动:握手的意思 2.找系统sdk\sam ...

  8. 模仿360安全卫士项目笔记2

    14_自定义对话框_40 1.画图两个对话框的样子: 2.写大体逻辑代码: showLostFindDialog();//进入手机防盗的对话框: isSetupPwd();//判断是否设置过密码,用到 ...

  9. 炫彩界面库-模仿360安全卫士8.8,支持透明,换肤

    炫彩界面库-模仿360安全卫士8.8 此示例程序使用炫彩界面开发,采用贴图方式实现,控件透明,换肤. 代码下载地址:点击打开链接  代码在炫彩界面库下载包中.

最新文章

  1. COM:追踪植物-微生物组互作的进化历史
  2. Boost:双图bimap与lambda表达式的测试程序
  3. Oracle入门(九A)之用户的权限或角色
  4. postgresql数据库安装及简单操作
  5. crontab 改成只读模式_以“三合一”模式推动提质增效 助力公司高质量发展
  6. BBcode 相关资源索引
  7. C语言小算法:ACSII码(多字节)和Unicode(宽字节)互转
  8. linux高级安全ssh限制利用PAM
  9. 逆向学习1-[脱壳技术]/篇1
  10. uniapp-App支付宝授权小记
  11. jdbc写入数据库乱码问题
  12. 网页授权 根据 code 获取请求用户信息的 accessToken
  13. Air780E模块RNDIS应用开发指南
  14. LaTex “too many unprocessed floats” 解决
  15. 模拟a标签实现带header的下载
  16. postman---postman参数化
  17. 谷歌 I/O 2019 将于 5 月 7 日举办;百度春晚红包被微信封杀
  18. js编码scape 解码unescape
  19. 【前端学习】Git的安装和基本使用方法和环境变量配置 时光大魔王
  20. (02) 任务(Jobs)和触发器(Triggers)

热门文章

  1. OJ题目 P1236 夺取宝藏问题(Ipomy)算法设计与分析实践题目
  2. java反射的三种方式以及一些常用方法
  3. android 添加splash,$Android启动界面(Splash)的两种实现方法
  4. 计算机一级难还是二级难 有什么区别
  5. Vue3和@types/node的类型不兼容问题
  6. vue移动端 实现公告栏文字上下滚动效果
  7. Ubuntu查看端口是否正在被使用
  8. oracle listagg 排序,oracle 行转列 listagg与wm_concat
  9. AFT.Arrow.v2.0.2002.01.02
  10. 小红书热词速看 | 古茗有何营销动作?