This paper mainly describes how to improve the efficiency of troubleshooting and locating a client development, and wrote a small tool practice and thinking, as well as other partners in the team can improve the efficiency of locating problems and verifying whether the function is accurate.

Author/Ma Jie Chinese University MOOC Team

Editor/Liu Zhenyu

One, foreword

China University MOOC is an online education platform jointly launched by netease and Higher Education Association, which undertakes the task of national high-quality open courses of the Ministry of Education and provides MOOC courses of well-known Chinese universities to the public. At present, Chinese university MOOCs have become the world’s leading Chinese MOOCs platform in terms of the number, quality and social impact of courses.

In everyday Android development, we often encounter the following problems: testing, operations, production. At this time the client development students need to quickly locate a specific page.

It is observed that in most cases, when the business side wants the developer to confirm the business logic of a sudden page, the client side developer often needs to spend a long time to reply to the business side. If the recent business may still remember, but there are many pages on the client side, want to quickly locate the specific business page, then need to spend more time to find the relevant page.

Therefore, the idea of this paper is how to quickly find the corresponding page, help to develop the business code quickly, and quickly reply to the questions raised by the business side.

Ii. Program implementation

When discussing plans, we need to compare existing plans and then choose a more effective method.

2.1 Common ways to solve problems

In Android development to solve the problems provided above, commonly used in the following three ways:

  • Open Android Studio, relying on source memory, copy 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'
Copy the code
  • Global search key copywriting.

The above three ways can solve the problem, but from the analysis of time efficiency, we can estimate how long each way takes:

First, according to personal experience, students familiar with the project code will take dozens of seconds at the fastest, or 10 minutes at the slowest;

Second, you can navigate to the page in seconds with ADB, but you need to remember the command or set the command shortcut in advance.

Third, if there are many same documents, you need to search several times, and the time may be 10 seconds to 1 minute.

The time efficiencies for all of these methods range from a few seconds to a few minutes, and generally require code or ADB development tools, depending on the development environment.

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

2.2 More efficient methods

In fact, the idea is very simple, is to write a development SDK for real-time attention to the current page information. This page contains the following information:

  1. What is the current Activity?
  2. What is the current Fragment?
  3. What parameters are passed to the current page, for example, in intent?

The renderings are as follows:

From the above information can be quickly located to the current page; Such gadgets are especially useful when a page is very deep; The fastest speed as long as a few seconds can quickly locate the page, the efficiency of dozens of times faster than; And in front of the test and product, can give him the current key parameters, such as: xxxId, buried point information.

2.3 Main implementation principles

The main job of the above gadget is to get the current Activity. There are several ways to get the current Activity:

  1. With RunningTaskInfo’s topActivity, this method has been disabled in later versions;
  2. Handwritten code management Activity, this method is more rough, maintenance is more troublesome;
  3. Obtain currentActivityThread from mActivities by reflecting ActivityThread.
  4. Using the AccessibilityService helper, this method gets less information;
  5. Through ActivityLifecycleCallback listening to gain;

By comparison, choose to use AccessibilityService and ActivityLifecycleCallback to try these two ways. The following is a brief description of the realization of these two methods, the comparison between them and the final choice.

2.3.1 ActivityLifecycleCallback way

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

Isn’t that easy? To avoid memory leaks, set topActivity to NULL at onDestroy. This method is simple and quick, and no permission application is required.

2.3.2 AccessibilityService way

  • Inheritance 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 = newComponentName( 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; }}Copy the code
  • The 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>
Copy the code
  • Need res/xm/accessibilityservice. XML file
<? xml version="1.0" encoding="utf-8"? > <! -- These options MUST be specified herein order for the events to be received on first
 start in Android 4.11. -->
<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"/>
Copy the code

Compared with ActivityLifecycleCallback, this way is relatively complex, but also is simple.

2.3.3 Comparison of the two methods

From the perspective of implementation, using ActivityLifecycleCallback more simple than AccessibilityService. However, the advantage of AccessibilityService is that it does not need to be integrated into its own app. It can be run independently, and you can see which Activity all the current pages belong to. It can be used across processes. Using ActivityLifecycleCallback must be integrated into your app.

In practice, we don’t just want to get the current Activity, we also want to know what current fragments are in the current Activity, what parameters the current Activity got from the previous Activity, Current details such as what are the parameters in the fragments of information, so only when it is integrated into the app is easy to get, so finally chose to use ActivityLifecycleCallback way.

2.3.4 More details on the page

General page information development, a simple point is an Activity and then simple layout, a complex basic are Activity + (ViewPager)Adatper + fragment, Sometimes there will be a ViewPager loaded with fragments inside the fragment, so it can take a lot of time for people who are not familiar with the code to find the corresponding business logic page and code. So page fragments are also important.


topActivity.getIntent().getExtras();// Get the page parameters for the activity
topActivity.getSupportFragmentManager().getFragments(); // Get fragments from the activity level
fragment.getChildFragmentManager().getFragments();// Fragments corresponding to fragments
fragment.getArguments() // Get the fragment page parameters
Copy the code

3. Examples for improving efficiency

With regard to page information collection, several usage scenarios are listed here to prove that efficiency has been improved:

  1. For the client developers, can quickly locate the current error page, especially the new development, or not familiar with the business, or the business page depth is relatively deep;
  2. Confirm the core parameters of the page. For example, the details page needs some IDS, and these detailed parameters do not need to be obtained by the way of the client colleague interruption point. Operation and testing can be checked by themselves.
  3. In the integration of the elite class and the cloud class, the test students can quickly distinguish which is the page in the elite class and which is the page in the cloud class, which is convenient for the test to know which business side the current page belongs to; (This scene is an internal integration project of netease)
  4. Page Full-link parameter transfer verification scenario. For example: click on the home page to transfer the conversion rate to the order page, usually develop their own verification, with this tool, the product can also check the verification from the test package after testing.

Iv. Page information Other ideas

As for the page information scenario, the following page information modes can be expanded:

  1. You can obtain adapter in RecyclerView; (There is a lot of layout logic, put into the ViewHolder of the Adapter)
  2. Webview current information monitoring; (Front-end colleague debugging)
  3. Network kanban monitoring; (Network request information for the current page)
  4. Do not connect the computer Logcat log to view kanban; (Access ADB information without connecting to a computer)
  5. Guide line, interface element position, corresponding element color. (UI walkthrough verification)

The above points are mainly based on the situation of their own app to determine whether it needs to be implemented and which implementation is cost-effective. What has been realized at present is basically what the individual thinks is relatively high cost performance.

Five, the summary

When we are confronted with a problem, we should first consider whether the problem is our own uncomfortable point, and then observe whether others have similar situation. What is the common solution to this problem? Are there tools to replace them? If not, is it possible to make a tool at a lower cost? Finally, to improve your own efficiency, if this tool can help others, then energy efficiency is even better.

-END-