小编Bar*_*oyd的帖子

什么是Android窗口中的"面板"?

Android窗口和相关页面的参考文档(例如,WindowManager.LayoutParams和Window.Callback)在很多地方引用"面板".例如,Window.Callback页面具有以下内容.

Window.Callback API从Window返回其调用者.这允许客户端拦截密钥调度,面板和菜单等.

public abstract查看onCreatePanelView(int featureId)

在API级别1中添加

实例化视图以在'featureId'面板中显示.您可以返回null,在这种情况下,将为您创建默认内容(通常是菜单).

参数featureId:正在创建哪个面板.

返回视图:要放置在面板中的顶级视图.

WindowManager.LayoutParams似乎将Panels视为Windows"类型",例如:

TYPE_APPLICATION_PANEL窗口类型:应用程序窗口顶部的面板.TYPE_APPLICATION_SUB_PANEL窗口类型:应用程序窗口顶部的子面板.TYPE_STATUS_BAR_PANEL窗口类型:从状态栏上滑出的面板在多用户系统中显示在所有用户的窗口上.TYPE_SYSTEM_DIALOG窗口类型:从状态栏滑出的面板在多用户系统中显示在所有用户的窗口上.

我也仔细阅读了源代码,但如果不花费数小时的时间就无法取得任何重大进展.

什么是Windows面板,如参考文档中所使用的那样?

在相关的说明中,featureId是什么?在上面的onCreatePanelView(int featureId)中,它似乎是用于指定面板的ID,但在其他上下文中,它似乎用于标识一组Windows功能,例如,用于Window.requestFeature():

public boolean requestFeature(int featureId)

在API级别1中添加

启用扩展屏幕功能.必须在setContentView()之前调用它.可以根据需要多次调用,只要它在setContentView()之前.如果未调用,则不会提供扩展功能.请求后,您无法关闭该功能.您可以使用FEATURE_CUSTOM_TITLE来使用其他标题功能.

参数featureId:所需的功能,由Window定义为常量.

返回:现在设置的功能.

谢谢,巴里

android android-windowmanager

12
推荐指数
1
解决办法
1489
查看次数

为什么没有用于获取当前活动的Android API?

问题是,我如何获得当前的活动?已经在Stackoverflow和其他网站上被问了几十次,并且有很多提议的方法.然而,它们都具有某种形式的缺点.

在这篇文章中,我假设Android的API中没有为此提供解决方案,例如:Application.getTask().getRootActivity().

如果有:-)那不是很好吗?

所以,要清楚,我不是要求答案我如何获得当前的活动?

相反,我问的是没有提供这种能力的原因.假设每个正在运行的应用程序都有一个任务(假设任务没有被清空)并且每个这样的任务都有一个root活动,那么提供对该根Activity的访问似乎很容易.

在没有提供这种访问的情况下,当它非常明确地需要时,这对我来说意味着Android架构有一些我不理解的基础.

我错过了什么?为什么Android API不提供此信息?

作为背景,这里是一个概述已经提出的一些方法的部分.我发现以下两个链接特别有用(下面的每个方法都在一个或两个链接中提供).

链接

途径

  • 静电钩
  • 反射
  • ActivityManager
  • 其他(Instrumentation,AccessibilityService,UsageStatsManager)`

ActivityManager

ActivityManager方法仅提供Activity类的名称,而不是当前的Activity实例.例如,对于Context实例c:

c.getSystemService().getActivityManager() .getAppTasks().get(0).getTaskInfo() .topActivity().getClassName()

反射

我最喜欢的是_AZ提出的反思,但这种方法很脆弱,因为它依赖于内部.我想从Android看到的是这种方法是通过标准API提供的,开发人员可以安全地依赖它.

静电钩

最常见的方法是使用静态挂钩来保存对当前运行的Activity的引用.钩子可以是按活动或按应用程序.通过保存/销毁钩子的值可以避免内存泄漏(例如,在onCreate()/ onDestroy(),onStart()/ onStop(),onPause()/ onResume()).但是,当涉及多个活动时(例如,由于生命周期重叠 - 见下文),可能会出现问题.

我实现了一个静态钩子方法,它执行以下操作(完全透明,我还没有实现#1 - 我目前正在使用per-Activity静态钩子,这是一个bug).

  1. 提供一个扩展Application以提供钩子的类.钩子包含一个堆栈; 堆栈中的每个节点都是一个简单的ActivityInfo类,它包含对Activity实例的引用以及该实例的状态(CREATED,STARTED,RESUMED).
  2. 提供一个名为ActivityTracker的类,用于扩展Activity.然后,我使用ActivityTracker扩展我的每个活动.ActivityTracker使用其生命周期回调来向/从堆栈推送/弹出自身并更新其状态 - 我的其他活动不必执行任何操作.

理论上,这将允许我始终知道任务的后台堆栈的完整状态 - 完整的活动集,包括根活动,以及它们的当前状态.然而,在实践中,有一个转折 - 当一个活动开始另一个活动时,它们的生命周期重叠.在此期间,在堆栈停止时偷看可能会产生意外的Activity实例.

来自:https://developer.android.com/guide/components/activities/activity-lifecycle.html#soafa,"协调活动":

以下是活动A启动活动B时发生的操作顺序:

  1. 活动A的onPause()方法执行.
  2. 活动B的onCreate(),onStart()和onResume()方法按顺序执行.(活动B现在具有用户关注点.)
  3. 然后,如果活动A在屏幕上不再可见,则执行onStop()方法

当然,这也可以管理.最重要的是,我们确实有一个可用于存储信息的全局上下文(应用程序),我们确实拥有有关活动生命周期转换的完整信息,因此我付出了足够的努力,我相信这种基于静态堆栈的方法可能会成为相当的子弹 - 证明.

不过最终

但最后我觉得我只是简单地重写代码,这些代码可能已经存在于内部,用于管理一个Activity后台堆栈,这就是为什么我要问(如果你忘记了):

为什么没有用于获取当前活动的Android API?


UPDATE


在这个更新中,我将总结我从这个主题以及我自己的实验和研究中学到的东西.希望这个摘要对其他人有用.

定义

我将根据https://developer.android.com/guide/components/activities/activity-lifecycle.html上的活动状态定义,对"活动可见性状态"使用以下定义.

-----------------------------------
Visibility State   Definition
----------------------------------- …
Run Code Online (Sandbox Code Playgroud)

android android-intent android-service android-activity

9
推荐指数
1
解决办法
1721
查看次数

适用于Jelly Bean和Google API的Android AVD -

我试图让Android AVD适用于Jelly Bean(API-16)和Google API(我在平台定义中都包含了这两个).运行AVD时,我会收到以下错误.

$ emulator -avd Nexus_7_API_16_With_Google_APIs

模拟器:错误:这个AVD的配置缺少一个内核文件!模拟器:ERROR:ANDROID_SDK_ROOT已定义(C:\ data\applications\Android\Sdk)但无法在C:\ data\applications\Android\Sdk\system-images\sub目录中找到内核文件

我已经阅读了Stackoverflow和其他网站上可以找到的所有类似实例,但似乎没有一个与我的情况相关.

与大多数配置文件不同,用于Jelly Bean和Google API的配置文件似乎位于附加组件而不是系统映像中.例如:

$ cd $ ANDROID_SDK_HOME/.android/avd/Nexus_7_API_16_With_Google_APIs.avd/config.ini

$ grep image config.ini

image.sysdir.1 =插件\插件-google_apis-谷歌-16 \图像\ armeabi-V7A

实际上,"system-image"似乎被硬编码到模拟器中(尽管有可能存在一条路径 - 请参阅Android Studio中的无法运行模拟器).

这对我来说非常像一个错误.

建议???

谢谢,巴里

android android-emulator android-studio

8
推荐指数
0
解决办法
370
查看次数

修复:无法通过wifi连接到adb

事实证明,adbd Insecure实际上是问题所在.当我禁用它时(通过运行应用程序并取消选中启用不安全的adbd,我能够通过wifi连接得很好.

此外,对于那些感兴趣的人,一旦这个工作,那么netstat -n确实显示了连接,即:

$ netstat -n 
Proto Recv-Q Send-Q Local Address          Foreign Address        State
tcp       0      0 0.0.0.0:5555               0.0.0.0:*              LISTEN
tcp       0      0 **192.168.0.169:5555**     192.168.0.50:51178     ESTABLISHED
tcp6      0      0 ::ffff:127.0.0.1:47514 :::*                       LISTEN
Run Code Online (Sandbox Code Playgroud)

巴里


我无法通过Wifi连接adb(它可以通过USB工作正常).

我已经阅读了这里和其他地方的各种帖子,但没有找到适合我的答案.

我已经尝试从我的笔记本电脑连接到两个不同的设备(三星S4,Nexus 7 2013(wifi)它在两种情况下均无法连接,但具有相同的错误消息,尽管具有特定设备的IP地址,例如:

无法连接到192.168.0.125:5555

这两款设备都采用了毛巾,SuperSU和"adbd Insecure".我可以从我的笔记本电脑ping 192.168.0.125,我已经关闭了我的笔记本电脑的病毒防护和防火墙.

我按照标准步骤:

  • adb kill-server
  • adb usb
  • adb设备
  • adb tcpip 5555
  • adb connect 192.168.0.125

我读到"netstat -n"应该显示一个新的套接字存在并监听端口5555(无法通过ADB通过ADB连接到Android - 我是否需要root访问权限?)但在我的情况下不会发生 - 它仅显示默认端口5037的localhost连接.

  root@deb:/ # netstat -n
  Proto Recv-Q Send-Q Local Address          Foreign Address        State
  tcp …
Run Code Online (Sandbox Code Playgroud)

sockets android adb android-wifi

7
推荐指数
1
解决办法
1万
查看次数

adb shell:无法使用 ESCAPE 键

我想vi在跑步时使用adb shell。启动“vi”很容易。但是,我发现按键ESC似乎无法接通,因此无法退出插入模式。

\n\n

更广泛地说,我似乎根本无法将字符发送ESC到 adb shell。我已经彻底扫描了网络,但找不到任何有类似问题的人(更不用说答案)。

\n\n

我在 Samsung S4 上运行 VRUFNK1。在 PC 端,我在 Windows 下从 Cygwin 运行“adb shell”命令。

\n\n

想法???

\n\n
\n\n

更新:这里有一些可能的线索。

\n\n
    \n
  1. adb shell 似乎不是问题。我可以在运行的文件中捕获 ESC
    \nod -cb > file,因此 ESC 似乎正在访问 adb shell 下运行的程序。
  2. \n
  3. 所有命令都会在我的“adb shell”中得到回显(就好像 set -v 已打开,但事实并非如此)。
  4. \n
  5. 我注意到输入似乎没有从“原始模式”下的 cygwin shell 发送到 adb shell——即,我输入的任何文本都会在本地缓冲,直到我按回车键——然后发送整行。我不确定为什么这会使 ESC 无效,但 vi 肯定不希望以这种方式接收输入,也许这表明我的环境中出现了异常情况。
  6. \n
\n\n

与 #1 类似,bash (Bash X) 似乎收到了它,尽管 bash 的回显很奇怪。我可以使用 ESC 在 bash shell …

vi shell android cygwin adb

6
推荐指数
1
解决办法
3063
查看次数

Android Windows:它们何时以及如何创建?

我已经阅读了标准的Windows相关文档,并通过一堆源代码,试图了解如何以及何时创建Android Windows.我相信我搂着它,并希望得到验证或纠正.

据我所知,只有两种方法来获取Window对象的句柄.

1. Activity's getWindow.
2. Dialog's getWindow method.
Run Code Online (Sandbox Code Playgroud)

在上述两种情况下,您都可以使用getWindow获取Window的句柄,然后使用句柄操作Window.

Windows也可以通过使用WindowManager的addView方法创建,但是无法获得此类Windows的句柄.这是一个非常令人困惑的区域,因为addView方法本身并不意味着创建一个Window,甚至在View Manager源代码中对它的注释只是说明如下.

Assign the passed LayoutParams to the passed View and add the view to
the window.
Run Code Online (Sandbox Code Playgroud)

因此,该方法似乎意味着将View添加到现有Window.但是,addView的第二个参数是一个WindowManager.LayoutParams实例,除其他外,它指定一个Window类型(例如,TYPE_SYSTEM_ALERT),暗示实际上正在创建一个Window.事实上,情况就是如此.以下是源代码中发生的事情的简要概述.(对于新手:您可以在许多不同的网站上浏览源代码;我最喜欢的是http://grepcode.com.)

  1. WindowManager实现了ViewManager接口,这是定义addView的地方.网址:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/ViewManager.java#ViewManager.addView%28android.view.查看%2Candroid.view.ViewGroup.LayoutParams 29%

  2. WindowManager类的实际实现称为WindowManagerImpl.它的addView调用WindowManagerGlobal的addView.网址:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/WindowManagerImpl.java#83

  3. WindowManagerGlobal的addView是真正完成工作的地方.网址:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/WindowManagerGlobal.java#WindowManagerGlobal.addView%28android.view.查看%2Candroid.view.ViewGroup.LayoutParams%2Candroid.view.Display%2Candroid.view.Window 29%

    1. 验证传入的参数是否为WindowManager.LayoutParams.
    2. 如果View具有父级,则调整布局参数.
    3. 确定新视图(也称为窗口)是否是面板窗口(即子窗口)并处理它.
    4. 创建一个新的ViewRootImpl.
    5. 添加View,ViewRootImpl和WindowManager.LayoutParams实例以分隔ArrayLists.
    6. 通过后者的setView方法将View和关联的参数添加到ViewRootImpl.
  4. ViewRootImpl的setView方法然后做了一堆低级工作.它会在各种错误情况下抛出"无法添加窗口..."消息的变体异常.根据ViewRootImpl的主要评论,它是"视图层次结构的顶层,在View和WindowManager之间实现所需的协议.这在很大程度上是WindowManagerGlobal的内部实现细节."

    网址:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/view/ViewRootImpl.java#ViewRootImpl.setView%28android.view.查看%2Candroid.view.WindowManager.LayoutParams%2Candroid.view.View 29%

WindowManagerGlobal似乎通过三个阵列跟踪多个Windows.据我所知,ViewRootImpl实际上是新窗口,它由WindowManagerGlobal管理.

基于以上所述,看来调用addView实际上创建了一个新窗口(尽管它被不同地称为视图和窗口)但是没有提供相关的Window类来访问它,因此开发人员不能得到它的句柄.

我的问题是:

  1. 除了上面提到的两个getWindow方法之外,还有办法获取Window实例的句柄吗?
  2. 事实上,addView是否创建了一个Window,如果有的话,有没有办法获得它的句柄?
  3. 是否有其他错误,如果是,在什么方面?

谢谢!巴里

android android-layout android-layoutparams

6
推荐指数
0
解决办法
416
查看次数