01_来电归属地服务的创建
通过类名. 提示出所有的属性和方法:反射
来电的时候,弹出窗口显示归属地:
分析:
1.监听电话的状态
a.来电:显示归属地
b.通话、关闭:关掉,不显示归属地
2. 显示归属地
自定义土司(原生土司只是纯文本,有渐变的动画,时间消失)
View:事件监听来消失
02_分析土司的源码
1.分析:
看系统的Toast源代码:
a, makeText方法
//构造土司对象,创建TN的实例 mTN = new TN();
Toast result = new Toast(context);
LayoutInflater inflate = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflate.inflate(com.android.internal.R.layout.transient_notification, null);
//土司显示的文本框
TextView tv = (TextView)v.findViewById(com.android.internal.R.id.message);
tv.setText(text);
result.mNextView = v;//把当前土司的view给mNextView属性
result.mDuration = duration;//土司显示的时长
return result;
b,show方法
if (mNextView == null) {
throw new RuntimeException("setView must have been called");
}
INotificationManager service = getService();
String pkg = mContext.getPackageName();
TN tn = mTN;
tn.mNextView = mNextView;
try {
service.enqueueToast(pkg, tn, mDuration);
} catch (RemoteException e) {
// Empty
}
c, TN的源代码
TN的构造函数: 初始化LayoutParams
TN() {
// XXX This should be changed to use a Dialog, with a Theme.Toast
// defined that sets up the layout params appropriately.
final WindowManager.LayoutParams params = mParams;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
params.format = PixelFormat.TRANSLUCENT;
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
params.type = WindowManager.LayoutParams.TYPE_TOAST;
params.setTitle("Toast");
}
public void handleShow() {
if (localLOGV) Log.v(TAG, "HANDLE SHOW: " + this + " mView=" + mView
+ " mNextView=" + mNextView);
if (mView != mNextView) {
// remove the old view if necessary
handleHide();
mView = mNextView;
mWM = WindowManagerImpl.getDefault();
final int gravity = mGravity;
mParams.gravity = gravity;
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
mParams.horizontalWeight = 1.0f;
}
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
mParams.verticalWeight = 1.0f;
}
mParams.x = mX;
mParams.y = mY;
mParams.verticalMargin = mVerticalMargin;
mParams.horizontalMargin = mHorizontalMargin;
if (mView.getParent() != null) {
if (localLOGV) Log.v(TAG, "REMOVE! " + mView + " in " + this);
mWM.removeView(mView);
}
if (localLOGV) Log.v(TAG, "ADD! " + mView + " in " + this);
*************//土司显示的真正代码
mWM.addView(mView, mParams);
trySendAccessibilityEvent();
}
}
因为在Activity关闭后土司依然存在,所以他是属于窗口Window的
2.分析结果:
土司是加载到WindowManager中的
mWM.addView(mView, mParams);
MView:土司组件
mParams:土司在WindowManager中显示的参数配置
03_自定义toast显示
04_拖动土司
前提:
取消掉 禁止触摸的属性:
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
去掉Toast的类型:
WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;/
给Toast加触摸事件:
view.setOnTouchLi
05_归属地样式
设置自定义土司的背景:
-
在设置中心中加个界面来选择背景
-
在显示Toast的时候,显示选择对的背景
存储到SP中,打开时读取
06_选择归属第样式
07_选中时改变imageview的背景
08_小火箭的发射
-
自定义toast来显示小火箭
-
小火箭喷火
图片的切换
-
冒烟的处理
在服务中打开Activity,要设置
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);// 在任务栈中显示,service没有任务栈
startActivity(intent);
09_短信的备份
-
读出短信
通过内容提供者,访问短信数据
-
把短信内容备份到文件中
文件:XML Json
-
显示备份短信进度的进度条(对话框和组件)
用户要求:用进度对话框来显示进度(子线程问题,在engine类里要传递Activity来更新UI)
静态内部类:
普通内部类:
foreach循环:
-
数组
-
Iterable
10_短信备份进度条
在短信备份按钮的下方用进度条显示备份的进度
在业务类中定义接口实现操作多个进度条:
public interface BackProgress{
void setMax(int max);
void setProgress(int progress);
void end();
void show();
}
11_json短信备份