android从放弃到精通 第八天 freedom

来源:互联网 发布:中国网络明星于凯微博 编辑:程序博客网 时间:2024/06/06 01:51
8-3短信提醒-自定义短信弹框提醒
//0关于前面的短信提醒接收不到的问题,有一点需要牢记在心,android6.0以上版本的权限问题,
,至少在当前的情况下,在android8.0的虚拟机上解决相应的问题的方法是在手机的设置里面将一堆杂七杂八的权限全部打开,我是一个很懒的人,所以当前情况下,我感觉把所有权限全部打开比较方便,反正也是虚拟机,不用担心什么用户信息安全方面的问题


private WindowManager.LayoutParams layoutParams;
//窗口提示
private void showWindow() {
wm = getApplication().getSystemService(Context.WINDOW_SERVICE);
//获取布局参数
layoutParams = new WindowManager().LayoutParams();
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
//定义标记
layoutParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
//这里参数的意思需要重新斟酌一下,毕竟是什么意思都不知道


//定义格式
layoutParams.format = PixelFormat.TRANSLUENT;
//定义类型
layoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
//加载布局
mView = View.inflate(getApplication(), R.layout.sms_item, null);


//添加view到窗口
wm.addView(mView, layoutParams);
}
//回复短信
private void sendSms() {
Uri uri = Uri.parse("smsto:" + smsPhone);
Intent intent = new Intent(Intent.ACTION_SENDTO, uri);
//设置启动模式
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("sms_body","");
startActivity(intent)
}




分析,不知为什么,这节的节奏感觉很乱,一会说这个一会说那个的感觉,所以对于这一节,我需要进一步进行相应的整理工作,首先是那啥,哦,对,先理清楚这节需要实现的主要目标和功能-需要在接收短信的时候在app界面进行显示(用自定义布局进行显示),然后用户点击显示界面的回复按钮会跳转到短信界面,差不多就是这些了,因为只是一半课程的半成品,这里还是缺乏了一些功能,就是弹出的界面是不会消失的,然后就是发送的信息为空的状况
另外还有一个我感觉比较麻烦的事情是什么呢,就是在各种方面我感觉自己需要进入界面的时候该打开的服务就已经打开了,而不是现在的明明已经在设置界面里面打开了对应的界面但是实际上我如果需要启动该界面的时候还需要进行一遍关闭然后打开的操作


实现的代码其实说烦也不烦,首先获取WindowManage然后设置对应的LayoutParams,然后使用LayoutInflater实例化对应的界面,然后将对应的界面添加到对应的wm中,这样一来接收到短信并显示弹出框的操作就完成了,然后是回复短信的功能,首先是获取对应的uri,创建inent对象,设置对应的参数,然后使用startActivity进行跳转就完成了


这里遇到了一个问题,耽误了我很多时间,但是真的感觉stackoverflow真的很厉害,每次都能解决我的问题
出现的错误是这样的:
SYSTEM_ALERT_WINDOW PERMISSION on API 26 not working as expected. Permission denied for window type 2002


然后大神给出的解决方法是这样的:
According to the documentation on Android 8.0 Behavior Changes for apps targeting Android 8.0:


Apps that use the SYSTEM_ALERT_WINDOW permission can no longer use the following window types to display alert windows above other apps and system windows:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
Instead, apps must use a new window type called TYPE_APPLICATION_OVERLAY.
So your app could target some lower version. In this case, your alert window will ...


always appear beneath the windows that use the TYPE_APPLICATION_OVERLAY window type. If an app targets Android 8.0 (API level 26), the app uses the TYPE_APPLICATION_OVERLAY window type to display alert windows.


个人很嘚瑟的说,个人英语水平看这个简直轻松,但是为了照顾大家我还是担任一下临时翻译的工作:
根据安卓面向安卓8.0的应用的性能修改文档:
所有使用了SYSTEM_ALERT_PERMISSION权限的app将不再能使用一下的window type去显示一个弹出的窗口来覆盖其他的应用和系统窗口界面:
TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR
取而代之的是,app必须使用一个新的window type - TYPE_APPLICATION_OVERLAY
所以,悲催的是,当你的app执行的是较低的一些版本时,在这种情况下,你的弹出窗口就会...
一直显示在那些使用TYPE_APPLICATION_OVERLAY的窗口底下被覆盖
如果一个app指定了8.0版本,这个app可以使用TYPE_APPLICATION_OVERLAY去展示这个提示框
比较费解,反正我是这么猜测的反正使用任何方法的时候,这个使用最新的type都是没有问题的= =,要是在低版本遇到问题我会在后续的文章中说明的,我的真机版本是5.0要是没有问题,那就是没有问题了= =


但是当前的问题是,当弹出这个窗口的时候,对屏幕的任何操作就无效了,也就是只有这个弹出界面才能获取到焦点.关于这些问题该怎么解决,等8-5的内容吧


8-5短信提醒-Dispatch事件分发
上一节的根本原因是事件分发还是没有能让创建的view接收到,所以这里需要进行布局的重写等操作
这里有一些东西比较有意思,首先是什么是事件分发机制,以及各种方面的知识
首先,每一个组件都有一个自己默认处理事件的机制,但是貌似看这么多的情况,貌似只有activity之间可以通过点击返回按钮就行对应的跳转返回操作,所以这里使用的貌似是LinearLayout的子类,所以需要自己定义对应的事件处理器,再重载对应的方法,调用的操作.


又是一块很新的东西,所以这里还是详细的分析和记录一下吧


首先自定义组件DispatchLinearLayout继承LinearLayout,这个布局是用于弹出窗


//定义接口
public static interface DispatchKeyEventListener {
dispatchKeyEvent(KeyEvent keyEvent);
}


在类中定义对应的接口,设置setget方法
重载public boolean dispatchKeyEvent(KeyEvent keyEvent) {
//如果不为空,说明调用了,去获取事件
if(dispatchListener != null) {
dispatchListener.dispatchKeyEvent(keyevent);
return true;
}
return false;
}


private DispatchLinearLayout.DispatchKeyEventListener mDispatchEventListener = new DispatchLinearLayout.DispatchKeyEventListener() {
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
//判断是否按返回键
if(event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
if(mView.getParent() != null){
wm.removeView(mView);
}
return true;
}
return false;
}
}


然后是对home键的监听,使用广播
public static final String SYSTEM_DIALOGS_REASON_KEY = "reason";
public static final String SYSTEM_DIALOGS_HOME_KEY = "homekey";
class HomeWatchReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
intent.getStringExtra(SYSTEM_DIALOGS_REASON_KEY);
if(SYSTEM_DIALOG_HOME_KEY.equals(reason)) {
L.i("我点击了HOME键");
if(mView.getParent() != null) {
wm.removeView(mView);
}
}
}


}
}
然后和之前广播注册一样的情况,进行再对应模块进行注册和注销的设定,单纯的从英文的角度来分析一下前面这一段代码进行分析吧,这里最令人费解的果然还是这两个字符串常量的问题了,首先是广播接收器进行操作的时候会接收到很多的intent,这点毋庸置疑,毫无疑问,在各方面都有感觉,然后是其次接收action的问题,这里拿获得的action和一个intent中的常量进行比较,按照英语的角度来看,这个常量的意思是,关闭窗口,或者是收起来对应的窗口或许更加贴切,但是关闭窗口的情况其实有很多种,这里就需要对其进行筛选了,也就是这里的getStringExtra()操作,对应的参数就是获取关闭窗口的原因,如果关闭窗口的原因是点击了homekey也就是这里的第二个自定义字符串常量,那么就将其移除,大概就是这样了.去试试代码吧= =


于是说,至此,短信这一块终于是搞定了,作为今天的余韵,顺便来查一下getParent()方法是什么意思吧.


Collator :按拼音排序List<String> list = new ArrayList<>(Arrays.asList("翁", "啊", "好", "月"));
Log.d(TAG, "before sort: " + list);
Collections.sort(list, Collator.getInstance(Locale.SIMPLIFIED_CHINESE));
Log.d(TAG, "after sort: " + list);


作者:name what
链接:https://www.zhihu.com/question/33636939/answer/250610631
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


另外关于getParent()的问题,这里就贴上对应的链接吧
http://ask.csdn.net/questions/212466

原创粉丝点击