Android | 在LogCat中打印活动任务栈

3
我想在LogCat上打印出我Android应用程序启动的所有任务及其中活动的名称。SDK中是否有任何API可以提供我这些信息?
注:我不能也不想使用adb shell命令,因为我想将日志打印在LogCat中。
注意:我已经搜索了很多,但我找到的都是我不能使用的adb shell命令。请在回答时记住这一点。
更新:
以下是我想要的两种情况的示例:
1. 应用程序从活动A开始运行,我结束它并启动活动B。然后我在活动B上按下一个按钮,启动活动C。现在我的默认任务应该是C->B,即当我按返回键时,我会看到活动B,并在按下返回键时完成应用程序并显示启动器。
2. 我依次打开活动A、B和C,然后使用带有Intent标志Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK的意图启动活动X,然后打开活动Y和Z。当前任务现在看起来像Z->Y->X。
所以,我想在logcat中打印出这些信息:
1. 在情况1中为C->B 2. 在情况2中为Z->Y->X

你试过这个吗?导入android.util.Log; Log.v("hi","hi"); - Yamen Nassif
https://developer.android.com/reference/android/util/Log.html - Yamen Nassif
我知道如何记录日志,我的问题是,当我进入多个活动并想要查看当前堆栈中的所有活动时,如何打印整个活动堆栈。 - MiaN KhaLiD
1
你为什么想要这样做? - David Wasser
5个回答

4

目前来看,使用SDK内的API无法直接实现我所尝试的内容。更多信息可以在此链接中找到:

如何获取我的应用程序任务列表和它们活动的堆栈?

我的解决方案:

我不得不在应用程序的基类中添加日志记录,打印活动的名称以及其任务ID,以便调试我面临的问题。这是我的基础活动类的代码:

public abstract class BaseAppActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("TESTING", "CREATED: " + getClass().getSimpleName() + " -- TASK ID: " + getTaskId());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("TESTING", "DESTROYED: " + getClass().getSimpleName() + " -- TASK ID: " + getTaskId());
    }
}

2
您可以在Android Studio中生成活动状态报告。它会向您显示当前(正在运行)活动的状态和路由。
请在“Android Monitor”中找到“系统信息”选项卡。

enter image description here

然后,Activity Manager State

enter image description here

然后,它将为您生成活动堆栈。查找ACTIVITY(全大写)。 enter image description here 希望这能帮助到您,尽管这可能不是记录方法。

是的,AS提供的这个功能非常好。我只是想要日志解决方案,否则这个和shell dumpsys解决方案是最好的。无论如何,还是谢谢! - MiaN KhaLiD
4
AS 3中这个功能已经消失了 :( - Gumby The Green

1
随着时间的推移,一些人可能已经转向了“单个活动与多个片段”模式(包括 Kotlin)。我们可以记录它们的返回堆栈。
fun FragmentManager.printBackStack() {
        Log.d("TAG", "BackStackEntryCount = $backStackEntryCount")
        for (i in 0 until backStackEntryCount) {
            Log.d("TAG", "    #$i is ${getBackStackEntryAt(i)}")
        }
}

Calling this from an activity would look like:

supportFragmentManager.printPackStack()

请记住,片段事务是异步工作的。因此,以下代码将产生意想不到的结果:
addSomeFragmentToBackStack("MyFragmentTag")
printBackStack()
// result doesn't include "MyFragmentTag"

相反,您需要延迟执行打印操作:

addSomeFragmentToBackStack("MyFragmentTag")
Handler().postDelayed(
    { printBackStack() },
    500 // ms delay
)

这个解决方案肯定不完美,但对于调试来说还可以(例如,在循环中调用时会由于 Handler 导致产生意外结果)


0
根据Android Developers的说明:
一般来说,你应该使用Log.v()、Log.d()、Log.i()、Log.w()和Log.e()方法来编写日志。然后你可以在logcat中查看这些日志。
import android.util.Log;
public class MyActivity extends Activity{
    private static final String TAG = "MyActivity";
    @Override
    public void onCreate(Bundle bundle){
        Log.v(TAG, "on create");
    }
}

更新

既然您想要跟踪活动的活动并且了解活动周期的工作方式。解决方案应该是这样的:

@Override
public void onPause(Bundle bundle){
    Log.v(TAG,"  activity A paused"); // or whatever 
}

另一个解决方案是在startActivity之前执行此操作,类似于这样:
Intent i = new Intent(ThisActivity.class,AnotherActivity.class);
Log.v(TAG,"A->b");
// Log.v(TAG,"Z -> Y -> X"); or what ever message you want to print
startActivity(i);

第三种解决方案是在不确定哪个活动将启动哪个意图时,提供一些信息。
在启动意图之前,在活动A中执行以下操作:
intent.putExtra("UActivity", "From A");

在 Activity B 中的 onCreate 方法中执行以下代码:
String from = getIntent().getStringExtra("UActivity");
if("From A".equals(from){
    Log.v(TAG,"A->B");
}else if("From C".equals(from){
    Log.v(TAG,"C->B");
}// etc else if

所以只需跟进生命周期并在正确的方法中打印正确的日志消息,这样就可以使其正常工作。


我知道如何记录日志,我的问题是,当我进入多个活动并想要查看当前堆栈中的所有活动时,我该如何打印整个活动堆栈。 - MiaN KhaLiD
活动堆栈是什么意思?你是指当活动不再处于活动状态时吗? - Yamen Nassif
我刚刚更新了我的问题,并提供了一个场景和我想要的示例。 - MiaN KhaLiD

0

看起来您对应用程序的日志记录生命周期感兴趣(针对组件 Activity、Fragments、App、Service、BroadcastReciever 等)。您可以通过创建一个超类并将其扩展到其生命周期方法中打印 Log 来实现,这样您就不需要每次都打印。您需要创建一个超级 Activity、超级 Fragment 等。

例如,以下代码将在应用程序每次由操作系统初始化时(通过启动器、BroadcastReciever 等)记录日志:

   public class LifeCycleApp extends Application {

        String TAG = "GUFRAN " + LifeCycleApp.class.getName();

        public LifeCycleApp() {
          Log.d(TAG, "LifeCycleApp: constructor");
        }

        @Override
        public void onCreate() {
          super.onCreate();
          Log.d(TAG, "onCreate: ");
        }

        // Called by the system when the device configuration changes while your component is running.
        // Overriding this method is totally optional!
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
          super.onConfigurationChanged(newConfig);
        }

        // This is called when the overall system is running low on memory,
        // and would like actively running processes to tighten their belts.
        // Overriding this method is totally optional!
        //Called when the overall system is running low on memory, and actively running processes should trim their memory usage
        @Override
        public void onLowMemory() {
          super.onLowMemory();
        }

        @Override
        protected void finalize() throws Throwable {
          super.finalize();
          Log.d(TAG, "finalize: ");
        }
    }

你可能想看一下这个 https://github.com/guffyWave/LifeCycle


这实际上不是我想要的。我只是更新了我的问题,并提供了一个场景和我想要的示例。 - MiaN KhaLiD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接