需要配置好android的开发环境后,打开cmd命令窗口
在命令窗口中输入,adb logcat>D:/loglog,输入D盘下
运行手机上app应用程序,需要获取到app应用程序
然后停止运行获取手机上logcat的文件,停止是直接按Ctrl+c
打开输出的文件
通过抓取到log的日志,找到相应activity的应用程序。
1 Android 手机屏幕顶部有一些有刘海屏, 会导致测量toolbar的高度不准,
private fun getNotchHeight(activity: Activity): Int {
if (BuildVERSIONSDK_INT >= BuildVERSION_CODESP) {
val windowInsets = activitywindowdecorViewrootWindowInsets
return windowInsetsdisplayCutoutsafeInsetTop : 0
}
return 0
}
获取的值如果不为0 , 说明有刘海屏, 获取到的数值就是刘海屏的高度(像素单位px)
2 默认的status bar高度为 24dp, toolbar 高度为56dp 一起的高度为80dp Android手机默认的高度值
3 当出现了刘海屏时, 值需要按功能需求获取 并且 其中"刘海屏的高度"包含了"Status bar的高度"
The extensive Android SDK allows you to do many great things with particular views like the WebView for displaying webpages on Android powered devices
Android SDK 的扩展通过使用特定的view允许你做许多事情比如WebView用来在Android手机上展示网页
As of lately while I was experimenting with the Android SDK I was using a WebView in one of my activities
最近我在体验Android SDK的时候在一个Activity中用到了WebView
From that particular WebView I needed to know the ContentHeight but also the ContentWidth
从WebView我不但想要知道ContentHeight还想知道ContentWidth
Now getting the contentHeight is easy like so:
现在的情况是获取contentHeight很easy如下
webviewgetContentHeight();
Unfortunately getting the contentWidth from a WebView is rather more difficult since there is not a simple method like:
不幸的是从一个WebView获取contentWidth是相当困难因为SDK中没有一个像这样的方法
// THIS METHOD DOES NOT EXIST!
webviewgetContentWidth();
There are ways to get the contentWidth of the rendered HTML page and that is through Javascript If Javascript can get it for you then you can also have them in your Java code within your Android App
当然是有方法获取contentWidth的就是通过Javascript来获取如果你能够支持Javascript那么你就可以在你的Android 程序中使用java代码来获取宽度
By using a JavascriptInterface with your WebView you can let Javascript communicate with your Android App Java code by invoking methods on a registered object that you can embed using the JavascriptInterface
通过在你的WebView中使用JavascriptInterface通过调用你注册的JavascriptInterface方法可以让Javascript和你的Android程序的java代码相互连通
So how does this work
怎么做呢?
For a quick example I created a simple Activity displaying a webview that loads a webpage wich displays a log message and a Toast message with the contentWidth wich was determined using Javascript Note that this happens AFTER the page was finished loading because before the page is finished loading the width might not be fully rendered Also keep in mind that if there is content loaded asynchronously that it doesnt affect widths (most likely only heights will be affected as the width is almost always fully declared in CSS files unless you have a % width webpage)
搭建一个快速的例子创建一个简单的展示webView的Activity一个LogCat消息一个Toast消息用来显示我们通过 Javascript获取的宽度注意这些会在网页完全加载之后显示因为在网页加载完成之前宽度可能不能够正确的获取到同时也要注意到如果是异 步加载这并不影响宽度(最多高度会受影响因为宽度总是在CSS文件中做了完全的定义除非在网页中你用了%宽度)
Below is the code of the Activity Mainjava:
下面的代码是Activity的代码
package compimmosandroidsampleswebviewcontentwidth;
import androidappActivity;
import androidosBundle;
import androidutilLog;
import androidwebkitWebView;
import androidwebkitWebViewClient;
import androidwidgetToast;
publicclass Main extends Activity {
privatefinalstatic String LOG_TAG = "WebViewContentWidth";
privatefinal Activity activity = this;
privatestaticint webviewContentWidth = ;
privatestatic WebView webview;
/ Called when the activity is first created /
@Override
publicvoid onCreate(Bundle savedInstanceState) {
superonCreate(savedInstanceState);
setContentView(Rlayoutmain);
webview = (WebView) findViewById(Ridwebview);
webviewgetSettings()setJavaScriptEnabled(true);
webviewsetSaveEnabled(true);
webviewaddJavascriptInterface(new JavaScriptInterface() "HTMLOUT");
webviewsetWebViewClient(new WebViewClient() {
@Override
publicvoid onPageFinished(WebView view String url) {
webviewloadUrl("javascript:windowHTMLOUTgetContentWidth(documentgetElementsByTagName(html)[]scrollWidth);");
}
});
webviewloadUrl(";);
}
class JavaScriptInterface {
publicvoid getContentWidth(String value) {
if (value != null) {
webviewContentWidth = IntegerparseInt(value);
Logd(LOG_TAG "Result from javascript: " + webviewContentWidth);
ToastmakeText( activity
"ContentWidth of webpage is: " +
webviewContentWidth +
"px" ToastLENGTH_SHORT)show();
}
}
}
}
Below is the XML layout used with the Activity wich only contains a simple WebView:
下面是Activity的Layout主要就是一个简单的WebView
<xml version="" encoding="utf">
<LinearLayout
xmlns:android=";
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<WebView android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
AndroidManifestxml layout:
AndroidManifestxml代码
<xml version="" encoding="utf">
<manifest
xmlns:android=";
package="compimmosandroidsampleswebviewcontentwidth"
android:versionCode="" android:versionName="">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name="Main"
android:label="@string/app_name">
<intentfilter>
<action android:name="androidintentactionMAIN" />
<category
android:name="androidintentcategoryLAUNCHER" />
</intentfilter>
</activity>
</application>
<usessdk android:minSdkVersion="" />
<usespermission android:name="androidpermissionINTERNET" />
</manifest>
You can also download the full source of Android Application WebViewContentWidth!
转载
RunningAppProcessInfo currentInfo = null;
Field field = null;
int START_TASK_TO_FRONT = 2;
String pkgName = null;
try {
field = ActivityManagerRunningAppProcessInfoclassgetDeclaredField("processState");
} catch (Exception e) {
return null;
}
ActivityManager manager = (ActivityManager) mContextgetSystemService(ContextACTIVITY_SERVICE);
List<RunningAppProcessInfo> appList = managergetRunningAppProcesses();
if (appList == null || appListisEmpty()) {
return null;
}
for (RunningAppProcessInfo app : appList) {
if (app != null && appimportance == RunningAppProcessInfoIMPORTANCE_FOREGROUND) {
Integer state = null;
try {
state = fieldgetInt(app);
} catch (Exception e) {
return null;
}
if (state != null && state == START_TASK_TO_FRONT) {
currentInfo = app;
break;
}
}
}
if (currentInfo != null) {
pkgName = currentInfoprocessName;
}
return pkgName;
上述代码走到field = ActivityManagerRunningAppProcessInfoclassgetDeclaredField("processState");这一句话的时候,走到了catch里面,返回空值,上面这句话有错吗
Activity作为安卓四大组件之一,是最重要也是用得最多的组件,涉及的知识点非常多,有些知识点平时开发很少用到,但在某些场景下需要特别注意,本文详细整理了Activity涉及的知识点,供开发参考。
针对Activity可以提出很多问题,如:
Activity 的生命周期?
Activity 之间的通信方式?
Activity 各种情况下的生命周期?
横竖屏切换时 Activity 的生命周期?
前台切换到后台,然后再回到前台时 Activity 的生命周期?
d出 Dialog 的时候按 Home 键时 Activity 的生命周期?
两个Activity之间跳转时的生命周期?
下拉状态栏时 Activity 的生命周期?
Activity 与 Fragment 之间生命周期比较?
Activity 的四种 LaunchMode(启动模式)的区别?
Activity 状态保存与恢复?
Activity的转场动画有哪些实现方式?
Activity的生命周期中怎么获取控件宽高?
onNewIntent的执行时机?
如何连续退出多个Activity?
如何把Acitivty设置成Dialog样式 ,android:theme="@android:style/ThemeDialog"
关于横竖屏切换的生命周期,对应不同的手机,由于厂商定制的原因,会有不同的效果,如设置了configChanges="orientation”在有些手机会执行各个生命周期,但有些手机却不会执行。
网上常见的结论如下:
但实际的测试如下:
可以看出,不同厂商的手机切屏生命周期会有差异。
从API 13以上,当设备在横竖切屏时,“屏幕尺寸”也会发生变化,因此为了杜绝切屏导致页面销毁重建,需要加上screenSize,使用设置4,即 android:configChanges="orientation|keyboardHidden|screenSize"
Activity的四种状态如下:
在activity处于paused或者stoped状态下,如果系统内存紧张,可能会被销毁,当重回该activity时会重建,正常返回和被回收后返回的生命周期如下:
如果是回收后返回,onCreate的参数savedInstanceState不为空。
有哪些场景会触发onNewIntent回调呢?跟启动模式有关,首先该Activity实例已经存在,再次启动才可能触发。一种情况是启动模式是singleTask或者singleInstance,无论该activity在栈中哪个位置,都会触发onNewIntent回调,并且把上面其他acitivity移除,另一种情况是启动模式是singleTop或者以FLAG_ACTIVITY_SINGLE_TOP启动,并且该activity实例在栈顶,会触发onNewIntent,如果不在栈顶是重新创建的,不会触发。
在实际业务开发中,往往碰到需要连续退出多个activity实例,下面整理了几种常见方法:
● 发送特定广播
1、在需要处理连续退出的activity注册该特定广播;
2、发起退出的activity发送该特定广播;
3、接收到该广播的activity 调用finish结束页面。
● 递归退出
1、用startActivityForResult启动新的activity;
2、前一个页面finish时,触发onActvityResult回调,再根据requestCode和resultCode处理是否finish,达到递归退出的效果。
● FLAG_ACTIVITY_CLEAR_TOP
通过intentsetFlag(IntentFLAG_ACTIVITY_CLEAR_TOP)启动新activity,如果栈中已经有该实例,则会把该activity之上的所有activity关闭,达到singleTop启动模式的效果。
● 自定义activity栈
1、自定义activity列表,新打开activity则加入栈中,关闭则移除栈;
2、需要退出多个activity时,则循环从栈中移除activity实例,并调用finish。
在讨论Activity启动模式经常提到任务栈,那到底什么是任务栈?
任务是一个Activity的集合,它使用栈的方式来管理其中的Activity,这个栈又被称为返回栈(back stack),栈中Activity的顺序就是按照它们被打开的顺序依次存放的。返回栈是一个典型的后进先出(last in, first out)的数据结构。下图通过时间线的方式非常清晰地向我们展示了多个Activity在返回栈当中的状态变化:
taskAffinity 任务相关性,可以用于指定一个Activity更加愿意依附于哪一个任务,在默认情况下,同一个应用程序中的所有Activity都具有相同的affinity, 名字为应用的包名。当然了,我们可以为每个 Activity 都单独指定 taskAffinity 属性(不与包名相同)。taskAffinity 属性主要和 singleTask 启动模式和 allowTaskReparenting 属性配对使用,在其他情况下没有意义。
taskAffinity 有下面两种应用场景:
分为显示启动和隐式启动。
(1)显示启动
直接指定待调整的Activity类名。
(2)隐式启动
Intent 能够匹配目标组件的 IntentFilter 中所设置的过滤信息,如果不匹配将无法启动目标 Activity。IntentFilter 的过滤信息有 action、category、data。
IntentFilter 需要注意的地方有以下:
● 一个 Activity 中可以有多个 intent-filter
● 一个 intent-filter 同时可以有多个 action、category、data
● 一个 Intent 只要能匹配任何一组 intent-filter 即可启动对应 Activity
● 新建的 Activity 必须加上以下这句,代表能够接收隐式调用
<category android:name="androidintentcategoryDEFAULT" />
只要匹配一个action即可跳转,注意的是action要区分大小写。
规则:如果intent中有category,则所有的都能匹配到intent-filter中的category,intent中的category数量可用少于intent-filter中的。另外,单独设置category是无法匹配activity的,因为category属性是一个执行Action的附加信息。
intent不添加category会匹配默认的,即 “android:intentcategoryDEFAULT”
如果上面例子,如果去掉intentsetAction("action_name"),则会抛出异常:
规则:类似action,但data有复杂的结构,只要匹配一个data并且与data中所有属性都一致就能匹配到Activity,只要有1个属性不匹配,都无法找到activity。
data的结构:
data 主要是由 URI 和 mimeType 组成的。
URI 可配置很多信息,的结构如下:
与url类似,例如:
mineType:指资源类型包括文本、、音视频等等,例如:text/plain、 image/jpeg、video/ 等
下面看下data匹配的例子:
只匹配scheme
只匹配scheme也是能匹配到activity的。
匹配scheme、host、port
将上面的data改为
匹配mineType
如果有mineType,则不能仅设置setData或setMineType了,因为setData会把mineType置为null,而setMineType会把data置为null,导致永远无法匹配到activity,要使用setDataAndType。
使用scheme的默认值content\file
注意该方法需要在startAtivity方法或者是finish方法调用之后立即执行,不能延迟,但可以在子线程执行。
而在windowAnimationStyle中存在四种动画:
activityOpenEnterAnimation // 打开新的Activity并进入新的Activity展示的动画
activityOpenExitAnimation // 打开新的Activity并销毁之前的Activity展示的动画
activityCloseEnterAnimation //关闭当前Activity进入上一个Activity展示的动画
activityCloseExitAnimation // 关闭当前Activity时展示的动画
overridePendingTransition的方式比较生硬,方法也比较老旧了,不适用于MD风格,google提供了新的转场动画ActivityOptions,并提供了兼容包ActivityOptionsCompat。
我们知道在onCreate和onResume里面直接获取到控件宽高为0,那有什么办法获取到控件的实际宽高?只要有onWindowFocusChanged、viewpost、ViewTreeObserver三种方式获取。
当用户点击桌面图标启动APP时,背后的流程如下:
我们看到的手机桌面是Launch程序的界面,点击应用图标会触发点击事件,调用startActivity(intent),然后通过Binder IPC机制,与ActivityManagerService(AMS)通讯,AMS执行一系列 *** 作,最终启动目前应用,大概流程如下:
通过PackageManager的resolveIntent()收集跳转intent对象的指向信息,然后通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity。如果有权限,则在新的task中启动目标activity,如果发现没有进程,则先创建进程。
如果进程不存在,AMS会调用startProcessLocked创建新的进程,在该方法中,会通过socket的通讯方式通知zygote进程孵化新的进程并返回pid,在新的进程中会初始化ActivityThread,并依次调用LooperprepareLoop()和Looperloop()来开启消息循环。
创建好进程后下一步要将Application和进程绑定起来,AMS会调用上一节创建的ActivityThread对象的bindAppliction方法完成绑定工作,该方法会发送一条BIND_APPLICATION的消息,最终会调用handleBindApplication方法处理消息,并调用makeApplication方法处理消息,加载APP的classes到内存中。
通过前面的步骤,系统已经拥有了该Application的进程,后续的启动则是从已存在其他进程中启动Acitivity,即调用realStartAcitvityLocked,该方法会调用Application的主线程对象ActivityThread的sheduleLaunchActivity方法,在方法中会发送LAUNCH_ACTIVITY到消息队列,最终通过handleLaunchActivity处理消息,完成Acitivty的启动。
Activity
Activity 的 36 大难点,你会几个?「建议收藏」
[译]Android Application启动流程分析
android开发中获取当前的Activity有多种情况;
在Activity中,this就是当前的Activity,例如thisstartActivity。
在Fragment中可以通过 getActivity()来得到当前装载这个Fragment的Activity。
通过Activity堆栈来获取当前显示的这个Activity
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
ComponentName cn = amgetRunningTasks(1)get(0)topActivity;
以上就是关于如何获取android app的Activity全部的内容,包括:如何获取android app的Activity、Android 手机刘海屏 的获取、Android开发中怎样获取WebView的内容宽度高度等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)