我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android 移除弹窗方案

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android 移除弹窗方案

系统裁剪–移除系统弹窗通知

前一阵子被拉去评估一个需求,有个物联网产品是建立在Android平台基础上的,Android中的一些弹窗提示不需要,客户说一定要移除掉。

首先有哪些需要去掉呢?Android常见的提示控件:

  • Dialog
  • PopWindow
  • Toast

Dialog 都是弹出性提示,弹一个窗口,像长按电源键关机重启选项,音量大小调节弹窗啊,低电电量提示都是用的这个控件,其中客户要求有些系统的提示还是需要保留的。
PopWindow 系统使用的不多,一般输入法弹出方式就是用的PopWindow,还有Spinner的选择弹窗也是使用的PopWindow
Toast 系统和应用基本都会用到的,没什么好介绍的。

一个一个弹窗找肯定是不现实的,我们直接从源头上解决。
首先是Dialog和Toast控件,这两个控件在显示时都需要调用.show()方法,我们在这里做文章:
1.在show方法里可以获取当前的调用包名,然后匹配一个白名单,客户应用可以放到这个白名单里,允许弹窗的可以让他弹,不允许的直接return
2.对于同一个应用包名中某些弹窗需要弹,某些弹窗不需要的,增加setForceShow方法,在需要显示弹窗调用的地方使用这个方法强制弹窗
代码逻辑大致如下:

private boolean mForceShow;public void setForceShow(boolean forceShow){    mForceShow = forceShow;}public void show() {    String pkg = mContext.getPackageName();    if(!pkg.equals("com.xxx.xxx") && //客户应用包名       !pkg.equals("com.android.inputmethod.latin") && //输入法包名       !pkg.equals("com.android.settings") && //Settings包名       !mForceShow){ //如果设置了mForceShow=true,就强制显示弹窗        return;    }......}

因为新加入一个setForceShow方法,原生API是没有的,这里需要将编译出的framework.jar导入到Android Studio中,否则AS在编译的时候会报找不到方法

PopWindow较为特殊,它触发显示的方法是invokePopup(),代码修改呢也是差不多的。

这时客户又报了新的需求,客户有个输入用户名界面,使用的常见的Edittext控件,他需要这个控件长安选中文字的时候不弹出Copy、Share、SelectAll等提示
这个其实是系统的剪切板功能,客户说不需要这个,OK其实这个也好修改,直接上代码:
frameworks/base/core/java/android/widget/Editor.java

boolean hasInsertionController() {    return mInsertionControllerEnabled;}boolean hasSelectionController() {    return mSelectionControllerEnabled;}

让这两个方法返回false就行了

此时客户又追加需求,在他的用户协议页面长按文字时会弹出一个拷贝分享的弹窗,他也不想要这个功能,而他的用户协议使用chromium-WebView界面显示的,然后客户应用包名又必须加白名单里,上面的setForceShow这个他们又嫌麻烦,系统这边很难进行修改,咱又没有客户源码,有咱也不敢改啊

怎么办呢?

通过打堆栈的方式发现,这个弹窗其实最后调用的也是PopupWindow,继续在invokePopup方法中添加逻辑判断了,但是invokePopup中不能直接毙客户应用包名,这时我想到能否通过判断invokePopup的调用堆栈来判断,首先先看一下堆栈:
这个堆栈中能看到org.chromium.android_webview和org.chromium.content.browser等字样

04-19 01:54:32.271  3757  3757 W System.err: java.lang.Exception: xxx04-19 01:54:32.271  3757  3757 W System.err: at android.widget.PopupWindow.invokePopup(PopupWindow.java:1575)04-19 01:54:32.271  3757  3757 W System.err: at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1347)04-19 01:54:32.271  3757  3757 W System.err: at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1313)04-19 01:54:32.271  3757  3757 W System.err: at org.chromium.android_webview.PopupTouchHandleDrawable.show(chromium-SystemWebView.apk-default-495156103:562)04-19 01:54:32.271  3757  3757 W System.err: at android.os.MessageQueue.nativePollOnce(Native Method)04-19 01:54:32.271  3757  3757 W System.err: at android.os.MessageQueue.next(MessageQueue.java:335)04-19 01:54:32.271  3757  3757 W System.err: at android.os.Looper.loopOnce(Looper.java:161)04-19 01:54:32.271  3757  3757 W System.err: at android.os.Looper.loop(Looper.java:288)04-19 01:54:32.271  3757  3757 W System.err: at android.app.ActivityThread.main(ActivityThread.java:7918)04-19 01:54:32.271  3757  3757 W System.err: at java.lang.reflect.Method.invoke(Native Method)04-19 01:54:32.271  3757  3757 W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)04-19 01:54:32.271  3757  3757 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:942)04-19 01:54:32.349  3757  3757 W System.err: java.lang.Exception: xxx04-19 01:54:32.350  3757  3757 W System.err: at android.widget.PopupWindow.invokePopup(PopupWindow.java:1575)04-19 01:54:32.350  3757  3757 W System.err: at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1347)04-19 01:54:32.350  3757  3757 W System.err: at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1313)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.widget.floatingtoolbar.LocalFloatingToolbarPopup.show(LocalFloatingToolbarPopup.java:371)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.widget.floatingtoolbar.LocalFloatingToolbarPopup.show(LocalFloatingToolbarPopup.java:346)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.widget.floatingtoolbar.FloatingToolbar.doShow(FloatingToolbar.java:227)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.widget.floatingtoolbar.FloatingToolbar.show(FloatingToolbar.java:167)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.view.FloatingActionMode$FloatingToolbarVisibilityHelper.updateToolbarVisibility(FloatingActionMode.java:386)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.view.FloatingActionMode.repositionToolbar(FloatingActionMode.java:217)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.view.FloatingActionMode.updateViewLocationInWindow(FloatingActionMode.java:167)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.view.FloatingActionMode.invalidateContentRect(FloatingActionMode.java:151)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.view.FloatingActionMode.invalidate(FloatingActionMode.java:145)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.policy.DecorView.setHandledFloatingActionMode(DecorView.java:2101)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.policy.DecorView.setHandledActionMode(DecorView.java:1941)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.policy.DecorView.startActionMode(DecorView.java:929)04-19 01:54:32.350  3757  3757 W System.err: at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:884)04-19 01:54:32.350  3757  3757 W System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1036)04-19 01:54:32.350  3757  3757 W System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1036)04-19 01:54:32.350  3757  3757 W System.err: at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:1036)04-19 01:54:32.350  3757  3757 W System.err: at android.view.View.startActionMode(View.java:7705)04-19 01:54:32.350  3757  3757 W System.err: at org.chromium.content.browser.selection.SelectionPopupControllerImpl.w(chromium-SystemWebView.apk-default-495156103:31)04-19 01:54:32.350  3757  3757 W System.err: at Rg0.a(chromium-SystemWebView.apk-default-495156103:1605)04-19 01:54:32.350  3757  3757 W System.err: at Zj0.i(chromium-SystemWebView.apk-default-495156103:259)04-19 01:54:32.350  3757  3757 W System.err: at b8.run(chromium-SystemWebView.apk-default-495156103:454)04-19 01:54:32.350  3757  3757 W System.err: at android.os.Handler.handleCallback(Handler.java:942)04-19 01:54:32.350  3757  3757 W System.err: at android.os.Handler.dispatchMessage(Handler.java:99)04-19 01:54:32.350  3757  3757 W System.err: at android.os.Looper.loopOnce(Looper.java:201)04-19 01:54:32.350  3757  3757 W System.err: at android.os.Looper.loop(Looper.java:288)04-19 01:54:32.350  3757  3757 W System.err: at android.app.ActivityThread.main(ActivityThread.java:7918)04-19 01:54:32.351  3757  3757 W System.err: at java.lang.reflect.Method.invoke(Native Method)04-19 01:54:32.351  3757  3757 W System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)04-19 01:54:32.351  3757  3757 W System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:942)

而在开发中我们是可以通过Thread.currentThread().getStackTrace()获取当前的调用栈的,你不仁我不义,上奇巧淫记,在invokePopup中添加如下代码

    String pkg = mContext.getPackageName();    for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) {        String className = stackTraceElement.getClassName();        if (pkg.equals("com.xxx") &&  //客户应用包名className != null && (className.contains("org.chromium.android_webview") ||  //判断调用堆栈是否包含chromium-WebView调用的关键classNameclassName.contains("org.chromium.content.browser"))) {            return;        }    }

当然以上方案也是有风险的,比如客户应用中所有使用chromium-WebView弹出提示的都会被屏蔽,客户如果换用其他内核的WebView可能导致className不匹配,功能失效,然而客户并不在乎

又有人问了,你通过getStackTrace方法不怕有什么风险吗?
其实要是仔细分析过源码,你会发现系统源码里很多地方都会使用这个,比如:

frameworks/base/core/java/android/os/Debug.java

@UnsupportedAppUsagepublic static String getCallers(final int depth) {    final StackTraceElement[] callStack = Thread.currentThread().getStackTrace();    StringBuilder sb = new StringBuilder();    for (int i = 0; i < depth; i++) {        sb.append(getCaller(callStack, i)).append(" ");    }    return sb.toString();}

后续

书接上次的移除系统弹窗的问题,发现了一个BUG,这里记录一下
测试报的现象:机器一定概率出现冻屏问题
好在概率很高,直接本地复现,此时屏幕一片黑,发现屏幕点击确实没反应,确实像是冻屏了,但是电源键可以亮灭屏,并且长按电源键也有关机选项弹窗,初步排除是冻屏问题

先得知道当前显示的界面是啥?
通过命令 adb shell dumpsys window | grep mFocus 看到当前显示的界面是客户应用界面,也就是客户应用可能出问题了
看看客户应用在干嘛。
通过adb shell ps -A | grep 加客户应用包名获取对应的pid(pidof命令也可以)
通过adb shell kill -3 pid 在data/anr生成对应的代码堆栈,间隔30S,再执行下,先看看两次主线程都在干嘛

 "main" prio=5 tid=1 Native  | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72b715b0 self=0xb4000073e61e47b0  | sysTid=3578 nice=-4 cgrp=top-app sched=0/0 handle=0x758de014f8  | state=S schedstat=( 332030820 23553030 494 ) utm=19 stm=13 core=7 HZ=100  | stack=0x7feab40000-0x7feab42000 stackSize=8188KB  | held mutexes=  native: #00 pc 00000000000a5c4c  /apex/com.android.runtime/lib64/bionic/libc.so (__ioctl+12) (BuildId: bf5f1ce73f89cca7d6a062eb7877e86a)  native: #01 pc 000000000005caa0  /apex/com.android.runtime/lib64/bionic/libc.so (ioctl+160) (BuildId: bf5f1ce73f89cca7d6a062eb7877e86a)  native: #02 pc 000000000005d08c  /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+284) (BuildId: e1935ad90ada7a9797034de30dc0d0da)  native: #03 pc 000000000005e2e8  /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+76) (BuildId: e1935ad90ada7a9797034de30dc0d0da)  native: #04 pc 000000000005e024  /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+224) (BuildId: e1935ad90ada7a9797034de30dc0d0da)  native: #05 pc 0000000000055aa0  /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+192) (BuildId: e1935ad90ada7a9797034de30dc0d0da)  native: #06 pc 00000000001769bc  /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+156) (BuildId: f24f1e660d8558246769c935ddc0acf7)  at android.os.BinderProxy.transactNative(Native method)  at android.os.BinderProxy.transact(BinderProxy.java:584)  at android.app.IActivityManager$Stub$Proxy.handleApplicationCrash(IActivityManager.java:4877)  at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:156)  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073)  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)  at java.lang.Thread.dispatchUncaughtException(Thread.java:2306)

都是在调用handleApplicationCrash方法,这个一般是应用发生崩溃后调用到的,通过IPC调用到system_server进程

同样的方法获取system_server的代码堆栈,搜索handleApplicationCrash看下对应的对端调用

  "binder:1783_B" prio=5 tid=160 Waiting  | group="main" sCount=1 ucsCount=0 flags=1 obj=0x140406b0 self=0xb400007c83d26090  | sysTid=3501 nice=-4 cgrp=foreground sched=0/0 handle=0x7a5330fcb0  | state=S schedstat=( 111610582 132912848 330 ) utm=5 stm=5 core=0 HZ=100  | stack=0x7a53218000-0x7a5321a000 stackSize=991KB  | held mutexes=  at java.lang.Object.wait(Native method)  - waiting on <0x064a7e5f> (a com.android.server.am.AppErrorResult)  at java.lang.Object.wait(Object.java:442)  at java.lang.Object.wait(Object.java:568)  at com.android.server.am.AppErrorResult.get(AppErrorResult.java:32)  - locked <0x064a7e5f> (a com.android.server.am.AppErrorResult)  at com.android.server.am.AppErrors.crashApplicationInner(AppErrors.java:653)  at com.android.server.am.AppErrors.crashApplication(AppErrors.java:569)  at com.android.server.am.ActivityManagerService.handleApplicationCrashInner(ActivityManagerService.java:8571)  at com.android.server.am.ActivityManagerService.handleApplicationCrash(ActivityManagerService.java:8463)  at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2086)  at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2653)  at android.os.Binder.execTransactInternal(Binder.java:1280)  at android.os.Binder.execTransact(Binder.java:1244)

AppErrors.crashApplicationInner方法调用到AppErrorResult.get方法

贴下AppErrorResult.java的代码:

final class AppErrorResult {    public void set(int res) {        synchronized (this) {            mHasResult = true;            mResult = res;            notifyAll();        }    }    public int get() {        synchronized (this) {            while (!mHasResult) {                try {                    wait();                } catch (InterruptedException e) {                }            }        }        return mResult;    }    boolean mHasResult = false;    int mResult;}

对照堆栈可以看到代码停在了get方法里的wait这边,这个wait的逻辑很好理解,只要mHasResult=false就一直wait,而整个代码中只有set方法会去修改这个mHasResult=true,通过添加log,进一步调试发现确实是set方法没有被调用到

在AppErrors中搜索下AppErrorResult.set方法的调用,发现都是在handleShowAppErrorUi方法里,

    services/core/java/com/android/server/am  (3 usages found)        AppErrors.java  (3 usages found)            handleShowAppErrorUi(Message)  (3 usages found)                840 res.set(AppErrorDialog.ALREADY_SHOWING);                853 res.set(AppErrorDialog.BACKGROUND_USER);                886 res.set(AppErrorDialog.CANT_SHOW);

梳理下应用崩溃时handleShowAppErrorUi的调用逻辑
->ActivityManagerService.handleApplicationCrash
->ActivityManagerService.handleApplicationCrashInner
->AppErrors.crashApplication
->AppErrors.crashApplicationInner
->sendMessage(ActivityManagerService.SHOW_ERROR_UI_MSG)
->AppErrors.handleShowAppErrorUi

crashApplicationInner方法的代码逻辑先是发一个message让UI线程去显示handleShowAppErrorUi,然后就是result.get等弹窗逻辑的返回

void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo,        int callingPid, int callingUid) {...        final Message msg = Message.obtain();        msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG;        taskId = data.taskId;        msg.obj = data;        mService.mUiHandler.sendMessage(msg);    }    int res = result.get();}

这个弹窗逻辑我们是修改过的,回退handleShowAppErrorUi中的修改确实没有这个问题了
之前我们的修改是直接注掉了弹窗显示,导致逻辑到这就断了,稍微修改一下,设置一个AppErrorDialog.CANT_SHOW的返回值

   void handleShowAppErrorUi(Message msg) {                    if ((mService.mAtmInternal.canShowErrorDialogs() || showBackground)                    && !crashSilenced && !shouldThottle                    && (showFirstCrash || showFirstCrashDevOption || data.repeating)) {//               proc.getDialogController().proc.getDialogController().showCrashDialogs(data);(data);                // set result AppErrorDialog.CANT_SHOW   if (res != null) {                    res.set(AppErrorDialog.CANT_SHOW);                }                if (!proc.isolated) {                    mProcessCrashShowDialogTimes.put(proc.info.processName, proc.uid, now);                }            } else {                // The device is asleep, so just pretend that the user                // saw a crash dialog and hit "force quit".                if (res != null) {                    res.set(AppErrorDialog.CANT_SHOW);                }            }        }    }

来源地址:https://blog.csdn.net/ztisen/article/details/130422043

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android 移除弹窗方案

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android弹出窗口实现方法

本文实例讲述了Android弹出窗口实现方法。分享给大家供大家参考,具体如下: 直接上代码:/** * 弹窗--新手指引 * @param cxt * @param id 资源编号 * @create_time 2011-7-27 下午0
2022-06-06

详解win7消除弹窗广告的方法

相信不少网友都有受到电脑弹窗广告的骚扰,在使用电脑的时候老是会有些软件捆绑的广告程序弹出,关掉后下次又会跑出来。小编想教网友如何在win7中关闭弹窗广告,以解决这个问题。方法一:1、找到【我的电脑】,鼠标右击【我的电脑】选择【管理】进入。2
2023-07-19

android PopupWindow 和 Activity弹出窗口实现方式

本人小菜一个。目前只见过两种弹出框的实现方式,第一种是最常见的PopupWindow,第二种也就是Activity的方式是前几天才见识过。感觉很霸气哦。没想到,activity也可以做伪窗口。 先贴上最常见的方法,主要讲activity的方
2022-06-06

Android popupWindow弹出窗体实现方法分析

本文实例讲述了Android popupWindow弹出窗体实现方法。分享给大家供大家参考,具体如下:1. 建立popupwindow显示的布局页面(普通的view任意布局)2023-05-31

Android移除Message的方法分享

本篇文章主要介绍MessageQueue提供的各种移除Message的方法,大概有八九个,接下来会对其中比较典型的移除方法进行详细分析,需要的可以参考一下
2022-11-13

win10永久删除广告弹窗的三种方法

  相信大家都被弹窗广告折磨过,小编也不例外,不知道要怎么删除广告弹窗好,而却最好是永久删除广告弹窗,小编今天就教你们3种方法,轻松解决这个问题!现在电脑上面下载的软件经常带一些各种各样的广告,每当玩游戏、看视频的时候突然跳出来,大家是不是
2023-07-10

Android Popupwindow弹出窗口的简单使用方法

本文实例为大家分享了Android Popupwindow弹出窗口的具体代码,供大家参考,具体内容如下代码很简单,没有和别的控件连用。布局自己随意定义,我的这个是最基础的,就直接上代码啦! 在MainActivity里import andr
2023-05-30

Android实现气泡布局/弹窗效果 气泡尖角方向及偏移量可控

Android 自定义布局实现气泡弹窗,可控制气泡尖角方向及偏移量。 效果图实现 首先自定义一个气泡布局。 public class BubbleRelativeLayout extends RelativeLayou
2022-06-06

有效将win10去除广告弹窗的方法汇总

在安装软件的时候,不小心安装了捆绑软件或者垃圾广告插件后,使用电脑的时候就会时不时弹出广告弹窗,关闭了下次开机还是一样出现怎么办。那么win10怎么去除广告弹窗?下面小编就教下大家win10去除广告弹窗的方法。方法一:禁用触发器1、打开计算
2023-07-10

android自定义消息弹窗的方法有哪些

Android中自定义消息弹窗的方法有以下几种:1. 使用AlertDialog:通过创建一个AlertDialog对象,并设置自定义的布局和样式来实现自定义消息弹窗。2. 自定义Dialog:通过创建一个继承自Dialog的自定义对话框类
2023-08-16

Flutter Android多窗口方案落地实战

这篇文章主要为大家介绍了Flutter Android多窗口方案落地实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-02-12

Android实现弹出登陆框的方案

下面是我的实现经历: 1.首先,我是直接使用AlertDialog来实现,确定是,形状有点难看,而且获得Dialog里面的控件略显麻烦(因为我要做的登陆框有一定的布局),然后就给我就放弃了,可能因为我太水了,不能很好的使用它 2.然后我就使
2022-06-06

android 浏览器之多窗口方案详解

我们Android平台是一个又一个的Activity组成的,每一个Activity有一个或者多个View构成。所以说,当我们想显示一个界面的时候,我们首先想到的是建立一个Activity,然后所有的操作在Activity里面实现,或者是一个
2022-06-06

Android监听输入法弹窗和关闭的实现方法

用过ios的都知道ios上输入法关闭的同时会自动关闭输入框,那么在android上如何实现监听输入法弹出和关闭呢?本篇文章就为你提供了一种可靠的实现方式。 演示效果视频地址 首先在AndroidManifest中配置android:wind
2022-06-06

Android应用内悬浮窗的实现方案示例

1、悬浮窗的基本介绍悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过WindowManagerService( WMS)来管理所有的窗口,对于WMS来说,管你是Activi
2023-05-30

在Android项目中实现一个底部支付弹窗的方法

在Android项目中实现一个底部支付弹窗的方法?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Android底部支付弹窗实现的效果:实现的思路:1.通过继承PopupWindo
2023-05-31

Android屏蔽软键盘自动弹出的解决方案

问题概述 在编辑框输入内容时会弹出软键盘,而手机屏幕区域有限往往会遮住输入界面,我们先看一下问题效果图: 输入用户名和密码时,系统会弹出键盘,造成系统键盘会挡住文本框的问题,如图所示: 输入密码时输入框被系统键盘遮挡了,大大降低了
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录