小编Jac*_*1re的帖子

使用activityManager.getRunningAppProcesses()获取(实际)前台进程

我正在尝试确定用户当前可见的应用程序.为此,我使用该activityManager.getRunningAppProcesses()方法.

我知道Android 5.1.1不支持该方法 - 这没关系.

一开始它就像魅力一样,我正在迭代RunningAppProcessInfos列表并检查重要性.

tl; dr获取当前前台进程和防止错误postives的正确方法是什么?如何完成列表的顺序 - API说它没有指定.有没有办法正确订购它们?

我做了什么:

不幸的是,ActivityManager返回的列表在每个设备上都是不同的.某些设备返回具有重要性100(即FOREGROUND)的多个信息,即使该过程当前不可见.

这引起了我有很多误报的问题.例如,我每次用facebook测试它并创建一个吐司,每次facebook都在前台.我切换到Home,所以我的启动器应该是前台进程.这是10秒之后,在那之后,facebook又重新出现在列表中的FOREGROUND(它不是开放也不可见)而且我得到了误报.

我认识到有些设备按照最近的流程排序列表.所以我决定尝试以下方法:

ActivityManager.RunningAppProcessInfo appProcess = appProcesses.get(0);
        final String processName = appProcess.processName;
        final String packageName = removeProcessSuffix(processName);
        if (appProcess.importance == FOREGROUND || appProcess.importance == VISIBLE){
            //do something, like the toast
        }
Run Code Online (Sandbox Code Playgroud)

使用appProcesses.get(0); 我只检查第一个元素,然后bug就消失了.再也没有误报了.

但是,现在在某些设备上,我根本不再获得前台进程.因为他们没有以任何方式订购列表.例如,一些4.2索尼智能手机是一些候选人.我得到了列表,但当前可见的进程是索引11左右.

我不知道该怎么做,以获得当前的前台进程,没有误报.

获取当前前台进程并防止错误假设的正确方法是什么?如何完成列表的顺序 - API说它没有指定.有没有办法正确订购它们?

谢谢!

android process activity-manager

19
推荐指数
1
解决办法
1571
查看次数

在应用更新时删除了活动别名

我已经实现了两个activity-alias用户应该能够在运行时启用或禁用的功能.

<activity-alias
    android:name=".ui.alias.open_location"
    android:targetActivity=".ui.activity.location"
    android:enabled="false">

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity-alias>
Run Code Online (Sandbox Code Playgroud)

我不希望在开始时启用它们,以免弄乱用户设备的应用程序屏幕.但在运行时,用户应该能够启用别名.我这样做是通过PackageManager:

PackageManager pm  = getApplicationContext().getPackageManager();
ComponentName componentName = new ComponentName(context, ".ui.alias.open_location");
pm.setComponentEnabledSetting(componentName,
                              PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                              PackageManager.DONT_KILL_APP);
Run Code Online (Sandbox Code Playgroud)

这在开始时就像魅力一样,但是当安装了我的应用程序的更新时,别名会再次被禁用.如何防止系统被清单覆盖启用状态?我不希望用户在开始时使用Launcher,我不希望用户在更新后重新创建所有别名快捷方式.

我想我需要类似的东西PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,但仅限于启用状态.

谢谢!

android android-manifest android-activity android-activity-alias

18
推荐指数
1
解决办法
778
查看次数

从TargetActivity中提取/区分ActivityAlias名称

我有多个ActivityAliases都开始一个单一TargetActivity.在我的内心TargetActivity我尝试区分开始的别名TargetActivity.

别名定义Manifest为可启动(intent-filter),它将在主屏幕上显示为快捷方式.用户将点击快捷方式,android将启动我在" android:targetActivity=.."标签中定义的活动.

对于我目前的提取componentNameIntent,这是考虑到我的TargetActivity和使用className().

喜欢:

String aliasName = targetActivity.getComponentName().getClassName();
Run Code Online (Sandbox Code Playgroud)

这适用于许多设备.但目前我在OnePlus上看到了一些失败.在该设备上,我的技术只返回我的TargetActivity的className,因此我无法根据用户启动的别名传递操作.

有没有其他可靠的方法可以ActivityAlias用来启动TargetActivity?它不需要是名称本身,只要我能区分它们.我不想为每个Alias创建专用的TargetActivities!

谢谢!

Ps.:我看到了另一种方法,它使用PackageManager来检索activityInfo并使用Activity.name.但我怀疑这会带来与我的第一种方法不同的东西.

ActivityInfo aInfo = activity.getPackageManager().getActivityInfo(activity.getComponentName(), PackageManager.GET_META_DATA);

String aliasName = aInfo.name;
Run Code Online (Sandbox Code Playgroud)

我也尝试过元数据:

编辑:

不幸的是,这种方法并不适用于所有设备.如果alias-className从activity.component 解析后返回 target-activity,那么元数据方法也会失败.

我继续寻找答案,并找到了一个很好的解决方法来区分TargetActivty中的别名.

您可以在ActivityAlias标记内提供元数据,如下所示:

<activity-alias 
    android:name=".aliasName" 
    android:enabled="false" 
    android:exported="true" 
    android:icon="@drawable/someIconRes" 
    android:label="@string/someLabelRes" android:targetActivity=".yourTargetActivity"> 
    <meta-data android:name="alias" android:value="valueToDistinguish"/>
    <intent-filter>  
        <action android:name="android.intent.action.MAIN"/> 
        <category android:name="android.intent.category.LAUNCHER"/> 
    </intent-filter> 
</activity-alias> …
Run Code Online (Sandbox Code Playgroud)

android android-manifest android-intent android-activity android-activity-alias

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

尽管区域设置配置更改由应用程序处理,Android 仍会重新启动活动

我按照在我的应用程序中实现每个应用程序语言首选项的路径进行操作 。如果用户第一次打开应用程序,则会向用户呈现选择一种可用语言的活动。

一旦用户选择了语言,AppCompatDelegateAPI 就会被调用,以通知 android 有关语言更改的信息。

// This code will be called some time after onCreate()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
  val selectedLanguageIso = "en"
  val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags(selectedLanguageIso)
  AppCompatDelegate.setApplicationLocales(appLocale)
}
Run Code Online (Sandbox Code Playgroud)

因为我不希望 android 重新创建此 Activity,所以我在 Manifest 中添加了该标志, android:configChanges="layoutDirection|locale"如下所示:

    <activity
        android:name=".LanguageActivity"
        android:screenOrientation="portrait"
        android:configChanges="layoutDirection|locale"/>
Run Code Online (Sandbox Code Playgroud)

但无论出于何种原因,android 都会忽略该标志并仍然重新创建我的 ActivityAppCompatDelegate.setApplicationLocales ,但只调用第一次。在导航到下一个活动之前,用户会看到奇怪的闪烁。

仅在第一次时才会被忽略。如果我第二次手动更改语言,那么该标志就会受到尊重。

我需要注意的是,我选择退出自动区域设置存储。所以 android 在第一个应用程序启动时不会有任何语言,直到我进行切换。也许这与这个问题有关。

      <service
          android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
          android:enabled="false"
          android:exported="false">
          <meta-data
              android:name="autoStoreLocales"
              android:value="false" />
      </service>
Run Code Online (Sandbox Code Playgroud)

有人有同样的经历吗?

编辑。添加我当前的解决方法用例

我当前的解决方法:

InitializePerAppLanguageUseCase我在我的第一个活动中使用ViewModel

视图模型:

// This code will be called …
Run Code Online (Sandbox Code Playgroud)

android android-appcompat

9
推荐指数
0
解决办法
582
查看次数

以优雅的方式检查两个参数为null

我正在迭代两个集合并检查两个集合是否包含相同的元素.我不能使用Java 8.


编辑1年后:

我在问题中创建了方法,以检查两个集合是否包含相同的元素,而不考虑我将两个Collection实现传递给方法的事实.

但Collection不确定元素的排序方式.我正在迭代收藏品.因此,Collection的某些实现可以以随机顺序保存元素,同时包含相同的元素.


如果所有元素都返回0 ,则两个集合都包含可比较的元素,并且内容定义为相等.x.compareTo(y)

如果其中一个为空,则将两个值定义为不同,而不是另一个.我想找到一种优雅的方法来比较nullity并防止对final进行null检查compareTo().

我目前的实施:

    public static <T extends Comparable<T>> boolean isSame(@Nullable Collection<T> a, @Nullable Collection<T> b) {

    if (a == null || b == null) {
        return (a == null && b == null);
    }

    if (a.size() != b.size()) {
        return false;
    }
    Iterator<T> aIt = a.iterator();
    Iterator<T> bIt = b.iterator();
    while (aIt.hasNext()) {
        T aValue = aIt.next();
        T bValue = bIt.next(); …
Run Code Online (Sandbox Code Playgroud)

java collections null iterator java-7

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

拖动时获取触摸位置

我有一些观点,我喜欢拖延.视图位于LinearLayout内,LinearLayout本身位于scrollview中.

我想得到当前手指的位置(触摸),在我的滚动视图上进行平滑滚动,具体取决于当前拖动的高度.

使用View内置侦听器startDrag长按一下后,我启动了我的draggin

view.startDrag(null, shadowBuilder, view, 0);
Run Code Online (Sandbox Code Playgroud)

我也能够在当前徘徊的视图上获得拖动的相对位置

view.setOnDragListener(new OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            //get event positions
        }
    });
Run Code Online (Sandbox Code Playgroud)

但这仅适用于拖动阴影当前所在的视图,而DragEvent仅提供相对位置,而不是原始位置.

我需要的是手指的位置,而阻力发生.不幸的是,所有onTouchEvents都会在拖动时消耗掉.

有人知道我是如何让这个工作的吗?

Ps:我目前使用的一种方式(种类)是通过dragEvent.relativePosition结合视图位置来计算触摸的位置.但是,还有更好的方法吗?

android drag-and-drop touch

5
推荐指数
1
解决办法
6313
查看次数

v7工具栏OptionsMenu菜单项最右边-如何添加边距

我在活动中使用了android.support.v7.widget.Toolbar。

我将其添加到活动的布局中,如下所示:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/add_contact_toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:background="@color/colorPrimary"
        android:elevation="6dp"
        android:title="@string/add_contact_toolbar_title"
        android:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>


</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

我在活动的onCreateOptionsMenu中为options菜单充气,然后为menu.xml充气:

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/add_contact_optionmenu_save"
        android:title="@string/add_contact_optionmenu_save"
        app:showAsAction="always"/>
</menu>
Run Code Online (Sandbox Code Playgroud)

但不幸的是,该项目看起来太靠右了,而且太小:

在此处输入图片说明

如何使它看起来像在所有其他应用程序中一样?更大,还有更多的边距?

干杯!

android android-layout

5
推荐指数
1
解决办法
2621
查看次数

使用Lint分析代码以获取需要权限的调用

我将targetSdkVersion设置为23,因此我想实现"在运行时请求权限".(见这里)

如果您忘记检查权限并且告诉您以下内容,Lint会直接调用:

调用需要用户可能拒绝的权限:代码应显式检查权限是否可用(带 checkPermission)或显式处理潜在的"SecurityException"

这是非常好的,我想分析我可能忘记的任何电话的代码,但我找不到我必须在我的检查配置文件中选择的Lint选项.

如何进行检查?谢谢!

android lint android-permissions

5
推荐指数
1
解决办法
980
查看次数

Android 6.0-危险权限和特殊权限有什么区别?

正如google 的指南指出的那样,有正常危险和特殊权限。

据我了解,危险是默认禁用的(这是真的吗?)。

如果某个应用程序声明它需要危险的权限,则用户必须将权限明确授予该应用程序。

这种感染还会更新还是仅新安装?

危险许可和特殊许可之间到底有什么区别?

Android说有特殊权限:

特殊权限 有些权限的行为与正常权限和危险权限不同。SYSTEM_ALERT_WINDOW和WRITE_SETTINGS特别敏感,因此大多数应用程序不应使用它们。如果应用程序需要这些权限之一,则它必须在清单中声明该权限,发送请求用户授权的意图。系统通过向用户显示详细的管理屏幕来响应此意图。

这与上面的引用不同吗?我没有区别。谢谢!

android android-permissions android-6.0-marshmallow

5
推荐指数
1
解决办法
1742
查看次数

用于动态链接事件的Firebase转换缺少广告系列归因

在应用程序和Firebase Google Analytics中使用了Firebase服务我有几个动态的深层链接,这些深层链接以编程方式在我的应用程序内部构建。(这些链接始终都可用于通知或新闻通讯)

当用户打开另一个用户收到的动态链接时,其中一个dynamic_link_*事件将触发并发送到分析。

我使用将utm参数添加到链接中DynamicLink.GoogleAnalyticsParameters.Builder并将dynamic_link_*事件标记为转换。我的utm参数是自定义参数,我没有用于它们的网络。

即:来源:my_application,媒介:share,活动:xyActivity

不幸的是,转换事件详细信息中既未设置广告系列,也未设置来源或媒体。

虽然,但我在StreamView中看到utm参数附加到了该事件

文档说,这将自动收集。但是不会,或者我做错了什么。

我认为这可能与事实有关,我的utm参数与任何网络都不相关。但是我找不到任何在转换详细信息的“网络设置”标签中添加自定义选项的选项。

先感谢您!


请查看下面的评论!转换总览花了将近1 1/2个月的时间!

在此处输入图片说明

firebase firebase-analytics firebase-dynamic-links firebase-console

5
推荐指数
0
解决办法
299
查看次数