头图

This article mainly describes how to improve the efficiency of a client's development, troubleshooting and positioning, and written the practice and thinking of a small tool, and other collaborators in the team can improve the efficiency of positioning problems and verify the accuracy of the function.

Author / Ma Jie China University MOOC Team

edit / Liu Zhenyu

I. Introduction

China University MOOC is an online education platform jointly launched by NetEase and the Higher Education Society. It undertakes the mission of the Ministry of Education's National Excellent Open Courses and provides the public with MOOC courses from well-known Chinese universities. At present, whether it is the quantity, quality or social influence of courses, Chinese University MOOC has become the world's leading Chinese MOOC platform.

In daily Android development, we often encounter some of the following problems: testing, operation, and product classmates ran over and said that there was a problem with this page, so hurry up and take a look. At this time, client development students need to quickly locate a specific page.

According to observations, in most cases, for the problem location of a sudden page, or when the business side wants the developer to confirm the business logic of this page, the client developer often takes a relatively long time to reply to the business side. . If you can remember the recent business, but there are more pages on the client side, and you want to quickly locate a specific business page, you need to spend more time looking for related pages.

So the idea of this paper is how quickly find the corresponding page , help develop quickly access business code , rapid response business issues raised by.

Second, the implementation of the program

When discussing options, we need to compare which options are currently available, and then choose a more effective method after the comparison.

2.1 Common ways to solve problems

To solve the above-mentioned problems in Android development, the following 3 ways are commonly used:

  • Open Android studio, rely on source code memory, copywriting memory to search;
  • Use the adb command to filter the current activity;
// windows
adb shell dumpsys window windows | Select-String -Pattern 'mCurrentFocus|mFocusedApp|mLastOpeningApp|mObscuringWindow'
  
// Mac
adb shell dumpsys window windows | grep -E 'mCurrentFocus|mFocusedApp|mLastOpeningApp'
  • Search key copy globally.

The above three methods can solve the problem, but from the time efficiency , you can estimate how long each method will take:

first type , according to personal experience, students who are familiar with the project code will take about tens of seconds at the earliest, and 10 minutes if it is slow;

The second type , use adb to locate the page in a few seconds, but you need to remember the command or set the command shortcut in advance;

third type , if there are a lot of the same copy, you need to search several times, and the time may vary from 10 seconds to 1 minute.

The time efficiency obtained by all the above methods ranges from a few seconds to a few minutes, and they are basically development tools that require code or adb and depend on the development environment.

Since it takes a lot of time, should we build a tool to improve positioning speed and improve positioning efficiency?

2.2 A more efficient method

In fact, the idea is very simple, that is, to write a developed SDK to follow the current page information in real time. The information on this page mainly contains the following information:

  1. Which is the current Activity?
  2. Which is the current Fragment?
  3. The parameters of the current page, such as: what are the various parameters in the intent?

are as follows:

It will be able to locate information quickly from the top to the current page; when the depth of a page to the very dark time, this gadget is especially useful; fastest speed just a few seconds will be able to quickly locate the page, efficiency Upgrade dozens of times faster than , and can show him the current key parameters in front of the test and product, such as xxxId, buried point information, etc.

2.3 Main realization principle

The main task of the above gadget is obtain the current Activity . There are mainly the following ways to obtain the current Activity:

  1. Through the topActivity of RunningTaskInfo, this method has been disabled in some subsequent versions
  2. Handwriting code to manage Activity, this method is crude and troublesome to maintain;
  3. Obtain currentActivityThread by reflecting ActivityThread and query it from mActivities;
  4. Use AccessibilityService this auxiliary function, this method obtains less information;
  5. Obtained by monitoring ActivityLifecycleCallback.

After comparison, choose to use AccessibilityService and ActivityLifecycleCallback these two ways to try. The following briefly talks about the realization of these two methods, and compares the two and the final choice.

2.3.1 ActivityLifecycleCallback method

    private static Activity topActivity;
        @Override
    public void onActivityResumed(Activity activity) {
        topActivity = activity;
    }

Is not it simple? In order to avoid memory leaks, you can set topActivity to null during onDestroy. In this way, simple and fast, and does not need to apply for permission.

2.3.2 AccessibilityService method

  • inherits AccessibilityService
@Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.d(TAG, "onAccessibilityEvent");
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            if (event.getPackageName() != null && event.getClassName() != null) {
                ComponentName componentName = new ComponentName(
                        event.getPackageName().toString(),
                        event.getClassName().toString()
                );
                ActivityInfo activityInfo = tryGetActivity(componentName);
                boolean isActivity = activityInfo != null;
                if (isActivity) {
                    Log.d(TAG, "CurentActivity " + componentName.flattenToShortString());
                    Log.d(TAG, "CurentActivity " + event.getPackageName().toString());
                }
            }
        }
    }
private ActivityInfo tryGetActivity(ComponentName componentName) {
        try {
            return getPackageManager().getActivityInfo(componentName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
    }
  • manifest configuration
<service
            android:name=".WindowChangeDetectingService"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/accessibilityservice"/>
        </service>
  • requires res/xm/accessibilityservice.xml file
<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
 start in Android 4.1.1 -->
<accessibility-service
    xmlns:tools="http://schemas.android.com/tools"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_description"
    xmlns:android="http://schemas.android.com/apk/res/android"
    tools:ignore="UnusedAttribute"/>

2.3.3 Comparison of the two methods

From the implementation perspective , using ActivityLifecycleCallback is easier than AccessibilityService. But AccessibilityService has the advantage that it does not need to be integrated into its own app, it can run independently, can view which Activity all current pages belong to, and can be used across processes. Use ActivityLifecycleCallback must be integrated into your own app.

In the practice process , in fact, we don’t just want to get the current activity, we also want to know which current fragments are in the current activity, which parameters the current activity obtains from the previous activity, and what are the current fragments Detailed information such as parameters can only be easily obtained when it is integrated into the app. So finally chose to use ActivityLifecycleCallback.

2.3.4 More detailed information on the page

For the information development on the general page, the simpler is an Activity and then the simple layout; the more complex is basically Activity + (ViewPager)Adatper + fragment, sometimes there will be ViewPager loaded with fragment in the fragment, for those who are not familiar with the code It still takes a lot of time to find the corresponding business logic page and code. So the page information fragment is also very important.


topActivity.getIntent().getExtras();// 获得 activity 的页面参数
topActivity.getSupportFragmentManager().getFragments(); // 获得 activity 一级中的 fragments
fragment.getChildFragmentManager().getFragments();// 对应 fragment 中的 fragments
fragment.getArguments() // 获得 fragment的页面参数

3. Examples of improving efficiency

Regarding page information collection, here are several usage scenarios to prove that the efficiency has been improved:

  1. For the client developer , he can quickly locate the current error page, especially when he is new to the development, or is unfamiliar with this business, or when the depth of the business page is relatively deep;
  2. core parameters of the . For example, the detail page needs some id, these detailed parameters do not need to be obtained by the client colleague's interruption point, and the operation and testing can be checked by themselves;
  3. When the fine class and the cloud class integrate , the test students can quickly distinguish which is the page in the fine class and which is the page in the cloud class, so that it is convenient for the test to know which business side the current page belongs to; (this scenario It is the internal integration project of NetEase)
  4. page full link parameter transfer verification scenario . For example, if you click on the homepage, you need to pass the conversion rate parameter to the order page. Usually, you develop your own verification. With this tool, the product can also be checked and verified from the test package after the test.

Fourth, other ideas on page information

Regarding the enhancement of the page information scene, the following page information methods are considered to be expandable:

  1. You can get the adapter in RecyclerView; (There is a lot of layout logic, put in the ViewHolder in the adapter)
  2. Webview current information monitoring; (front-end colleague debugging)
  3. Monitoring of network billboards; (network request information of the current page)
  4. Do not connect to the computer Logcat log to view the board; (no need to connect to the computer, get adb information)
  5. The reference line, the position of the interface element, and the color of the corresponding element. (Verification of UI walkthrough)

The above points are mainly to judge whether they need to be implemented according to the situation of their own app, and to judge which implementations are more cost-effective. What has been achieved so far is basically what I think is more cost-effective than .

V. Summary

When we encounter a problem, we first think about whether the problem is more uncomfortable for ourselves, and then observe whether other people have similar situations. What is the common solution to this problem? Is there a tool to replace it? If not, can you make a tool at a relatively low cost? Finally, to improve your own efficiency, if this tool can help others, then the energy efficiency will be even better.

-END-


有道AI情报局
788 声望7.9k 粉丝