Conclusion directory

  • View articles
    • How to understand that non-main thread can update the UI
    • DialogFragment full screen left left empty solution
    • DialogFragment full screen status bar black layout solution
    • Multiple fragments switch overlapping solutions
    • Multiple fragments possible TransactionTooLargeException solution when saving state
    • Recyclerview invokes notifyItemRemoved method to remove an Item that causes crash due to reference position
    • Recyclerview Local refresh Item because of the default animation caused flashing solution
    • Inexplicable offset scrolling appeared in recyclerView item
    • Recyclerview content is more than one screen, findFistCompletelyVisibleItemPosition will return 1
    • Recyclerview ViewHolder can not be filled layout problem solution
    • Textview rich text click event intercepts the solution of long press event
    • How do I disable ViewPager sliding
    • How to simulate mushroom Street/hornet’s Nest Viewpager loading pictures after switching when dynamic change height
    • How do I control the location of appbarLayout
    • How do I disable appbarLayout scrolling
    • Edittext failed to respond to a solution for the onClickListener event
    • Using listView or GridView to handle item state_selected events is not an effective solution
    • Solve the above 5.0 Button shadow effect scheme
    • For the difference between onSingleTapUp and onSIngleTapConfirmed
    • How to draw triangles using layer-list
    • On the property animation rotating View part of the model View flicker solution
    • Notes under code layout about ConstraintLayout
    • TextView in version 6.0 has single-line tail thumbnail pits
    • EditText automatically gets the solution to the problem caused by focus
  • Service report
    • There is no solution for enabling notifications in Service to disappear after manually cleaning up the application in the background
    • The global Context uses a more elegant fetching scheme
  • Thread article
    • It is recommended that new threads do not call network requests randomly. Generally, newthreads do not have looper queues. Refer to handlerThread
  • Network article
    • Retorfit Resolution of error in request parameters
  • Data report
    • How to gracefully handle multithreaded read and write problems in SQLite
    • How to transfer data to understand the Intent TransactionTooLargeException problems
  • Model system adaptation
    • How to solve the problem that the NatigationBar is blocked by the PopupWindow
    • How to solve the problem that MIUI system background cannot toast
    • How to solve the problem that toast cannot pop up when the notification bar permission is closed
    • How to adapt vivo and other double-sided screens
    • How do I solve the problem that Huawei devices generate too much broadcast and crash
    • How can I solve the problem that AdView is not displayed on Huawei devices
    • All kinds of notification bar adaptation scheme
    • Solve the problem of meizu push content restriction
    • Solve the problem that the application starts after the system is installed and the Launcher starts repeatedly after the Home is hidden
    • For an application with launcher as an Activity, you will receive notifications from a third party (Xiaomi, Huawei, Meizu) or share it when it is not started at all
    • The scene judgment analysis under the multi-scene pull up scenario of App
    • 8.0 ROM Only fullscreen Opaque Activities can request orientation solution
    • 9.0 Android Support for Plaintext Connections (Http)
    • 10.0 Solution to obtaining IMEI Exception
  • Build a build
    • Travis – Ci higher version of androidO compilation encountered a license failed compilation solution
    • The Android version supported by Dalvik has some limitations on subcontracting execution
    • Dalvik subcontract to build the possible Java. Each dex file lang. NoClassDefFoundError
    • Java 8 methods of java.lang.Long and java.lang.Character are not desugared by D8
    • FindBinding vs getBinding scenarios in Databinding
    • Gradle sync failed: Cannot choose between the following configurations of project
    • Gradle configures local offline packages
    • Fixed segmentation and whitespace in KVM/JVM -classpath compilation
    • Databinding NoSuchMethodError with buildTool 3.4.0
    • The debugging message debug info can be unavailabe is displayed
    • Project agent on Mac to clear gradle cache
  • Version control section
    • Git modifies the commit record
    • Git ignore does not take effect
  • other
    • After the ExoPlayer answers the call, the mute status of the original set Source will disappear, and the video may suddenly sound when the app is returned to resume
    • Please select Android SDK
    • About Java character and byte encoding relationship understanding
    • On the length calculation of emoji code
    • Do not use System.CurrentTimemillis () as a time log for business scenarios

<< View >>

  • How to understand that non-main thread can update the UI

    Google checks the UI update thread in View Blog

    void checkThread() {  
        if(mThread ! = Thread.currentThread()) { throw new CalledFromWrongThreadException("Only the original thread that created a view hierarchy can touch its views."); }}Copy the code

    This judgment is not executed when onCreate is executed

  • DialogFragment full screen left left empty solution

    Rearrange the window layout in fragment#onResume

    android.view.WindowManager.LayoutParams lp = window.getAttributes();
    lp.width = WindowManager.LayoutParams.MATCH_PARENT;
    lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
    window.setAttributes(lp);
    Copy the code
  • DialogFragment full screen status bar black layout solution

    Set in the theme

    <item name="android:windowIsFloating">true</item>
    Copy the code

    The window is wrap_content, and if left and right Spaces are left, the solution to the previous problem is considered.

  • When the application goes back to the background for a while and comes back, the Fragment switches to the overlapping solution

    In an online project we encountered a scenario where the application would press Home to return to the background and then, after some time, pull up our project from the background. Very few models have overlapping fragments when switching multiple fragments on the home page. After positioning, it was found that the operation and storage of these models were small and the performance deviation was caused by the pressure of memory. The system did not know which of the background programs needed to be kept running, so it tried to reclaim the pages that occupied large memory. When our pages were destroyed by the system, FragmentActivity# onSaveInstanceState is executed and holds some transient information, such as the view information of the interface fragment. When we pull up the application again, the original fragmentActivity will rebuild and rebuild a new fragment, which will overlap on top of the restored fragment.

    A more violent approach is to stop an activity from saving state, for example

    @ Override public void onSaveInstanceState (Bundle outState) {/ / don't directly call super onSaveInstanceState (outState); / / or directly empty data super. OnSaveInstanceState (new Bundle ()); }Copy the code

    The elegant way to do this is to say, for example

    @Override public void onSaveInstanceState(Bundle outState) { getSupportFragmentManager().putFragment(outState, you_key, CusFragment); super.onSaveInstanceState(outState); Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
        if(savedInstanceState ! = null) { CusFragment fragment = (CusFragment)getSupportFragmentManager().getFragment(savedInstanceState, you_key); }else {
        	  //init CusFragment
        }
    }
    Copy the code
  • Multiple fragments possible TransactionTooLargeException solution when saving state

    Appeared abnormal TransactionTooLargeException, because we used the online FragmentStatePagerAdapter as fragments adapter to as a cache read fragments in order to obtain better experience, Host multiple FragmentStatePagerAdapter# saveState and will be called for each fragment to save bundles of data. Because of our bundle is larger, the fragments and save bundles are not be destroyed and destroyed, so need to save bundles of data will continue to increase, until TransactionTooLargeException anomalies. We can override saveState and discard the States content by referring to stackOverflow.

    public Parcelable saveState() {
        Bundle bundle = (Bundle) super.saveState();
        bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out
        return bundle;
    }
    Copy the code

    The toolargeTool tool is also recommended to monitor page memory changes in real time during development.

  • Recyclerview invokes notifyItemRemoved method to remove an Item that causes crash due to reference position

    The notifyItemRemoved method does not remove data items from the data source of the list, causing data in the data source to be inconsistent with the number of items in the list. The data source needs to be updated synchronously.

  • Recyclerview Local refresh Item because of the default animation caused flashing solution

    Because recyclerView exists ItemAnimator, and triggered when deleting/updating/inserting Item, you can set not to support this animation.

    ((SimpleItemAnimator)recyclerView.getItemAnimator()).setSupportsChangeAnimations(false);
    Copy the code
  • Inexplicable offset scrolling appeared in recyclerView item

    The problem is located and a view that exists in the Viewholder may grab focus ahead of time. At the same time. Alibaba-vlayout library also found feedback changes. Issues – 255 solution is to add android: outer parent layout in Recyclerview descendantFocusability = “blocksDescendants” cover Recyclerview preemption priority focus for the parent layout.

  • Recyclerview content is more than one screen, findFistCompletelyVisibleItemPosition will return 1

    The reason is that the calculated start and end in findOneVisibleChild has exceeded the start and end in ReclclerView. After studying the source code to get the following.

    findFirstCompletelyVisibleItemPosition -> -1 findLastCompletelyVisibleItemPosition -> -1 findFirstVisibleItemPosition -> Normal findLastCopy the code
  • Recyclerview ViewHolder can not be filled layout problem solution

    The reason is that the argument at the end of the LayoutInflater#inflate() is passed incorrectly when the Holder is built. If null is passed, the width and height of the view loaded by the default XML layout will become invalid

    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_layout,parent, false);
        MyHolder holder = new MyHolder(view);
        return holder;
    }
    Copy the code

    The new version no longer has this problem.

  • Textview rich text click event intercepts the solution of long press event

    This problem is common in a list of messages that use ClickableSpan to handle rich-media click events and that need to support long-press replication. Since the LinkMovementMethod method always returns true on onTouchEvent, you can do this by customizable View.onTouchListener instead of setMovenmentMethod.

    public class ClickMovementMethod implements View.OnTouchListener {
    private LongClickCallback longClickCallback;
    
    public static ClickMovementMethod newInstance() {
        return new ClickMovementMethod();
    }
    
    @Override
    public boolean onTouch(final View v, MotionEvent event) {
        if(longClickCallback == null) { longClickCallback = new LongClickCallback(v); } TextView widget = (TextView) v; // MovementMethod is set to null to prevent consumption of the long-press event widget.setMovementMethod(null); CharSequence text = widget.getText(); Spannable spannable = Spannable.Factory.getInstance().newSpannable(text); int action = event.getAction();if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP) {
            int x = (int) event.getX();
            int y = (int) event.getY();
            x -= widget.getTotalPaddingLeft();
            y -= widget.getTotalPaddingTop();
            x += widget.getScrollX();
            y += widget.getScrollY();
            Layout layout = widget.getLayout();
            int line = layout.getLineForVertical(y);
            int off = layout.getOffsetForHorizontal(line, x);
            ClickableSpan[] link = spannable.getSpans(off, off, ClickableSpan.class);
            if(link.length ! = 0) {if (action == MotionEvent.ACTION_DOWN) {
                    v.postDelayed(longClickCallback, ViewConfiguration.getLongPressTimeout());
                } else {
                    v.removeCallbacks(longClickCallback);
                    link[0].onClick(widget);
                }
                return true; }}else if (action == MotionEvent.ACTION_CANCEL) {
            v.removeCallbacks(longClickCallback);
        }
    
        return false;
    }
    
    private static class LongClickCallback implements Runnable {
        private View view;
    
        LongClickCallback(View view) {
            this.view = view;
        }
    
        @Override
        public void run() {// Find a View that can consume long press events v = View; boolean consumed = v.performLongClick();while(! consumed) { v = (View) v.getParent();if (v == null) {
                    break;
                }
                consumed = v.performLongClick();
            }
        }
    }
    }
    
    textView.setOnTouchListener(ClickMovementMethod.newInstance());
    Copy the code
  • How do I disable ViewPager sliding

    Overwrite ViewPager onTouchEvent and onInterceptTouchEvent and return false without handling any sliding events

    @Override
    public boolean onTouchEvent(MotionEvent arg0) {
        return false;
    }
    
    @Override
    public boolean onInterceptTouchEvent(MotionEvent arg0) {
        return false;
    }
    Copy the code
  • How to simulate mushroom Street/hornet’s Nest Viewpager loading pictures after switching when dynamic change height

    ImageViewPager is a normal Viewpager object

    ImageListInfo is the list storing image information, imageShowHeight is the display height required by the service, which can be adjusted by dynamic calculation when switching

            imageViewPager.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() { imageViewPager.getViewTreeObserver().removeOnGlobalLayoutListener(this); // Stretch the width of the display image to adjust the height according to the viewPager height. ViewGroup.LayoutParams layoutParams = imageViewPager.getLayoutParams(); layoutParams.height = imageListInfo.imageShowHeight[0]; imageViewPager.setLayoutParams(layoutParams); }}); imageViewPager.setAdapter(imagePagerAdapter); imageViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                    if (position == imageListInfo.getImageListSize() - 1) {
                        return;
                    }
                    int height = (int) (imageListInfo.imageShowHeight[position] * (1 - positionOffset) + imageListInfo.imageShowHeight[position + 1] * positionOffset);
                    ViewGroup.LayoutParams params = imageViewPager.getLayoutParams();
                    params.height = height;
                    imageViewPager.setLayoutParams(params);
                }
    
                @Override
                public void onPageSelected(int position) {
                    if(! clickListBySelf) { toSelectIndex(imageListInfo.selected, position); } } @Override public void onPageScrollStateChanged(int state) { } });Copy the code
  • How do I control the location of appbarLayout

    CoordinatorLayout.Behavior behavior =((CoordinatorLayout.LayoutParams)mAppBarLayout.getLayoutParams()).getBehavior();
    if (behavior instanceof AppBarLayout.Behavior) {
          AppBarLayout.Behavior appBarLayoutBehavior = (AppBarLayout.Behavior) behavior;
          int topAndBottomOffset = appBarLayoutBehavior.getTopAndBottomOffset();
          if(topAndBottomOffset ! = 0) { appBarLayoutBehavior.setTopAndBottomOffset(0); }Copy the code
  • How do I disable appbarLayout scrolling

    CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams();
    AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior();
    behavior.setDragCallback(new AppBarLayout.Behavior.DragCallback() {
        @Override
        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
            return false; }});Copy the code
  • Edittext failed to respond to a solution for the onClickListener event

    Edittext listens for the click event of an Edittext that does not get focus. The first click triggers OnFocusChangeListener, and only responds to onClickListener when focus is obtained

  • Using listView or GridView to handle item state_selected events is not an effective solution

    Set Android:choiceMode=”singleChoice” to the listView or GridView in the XML layout and use the state_activated state instead of the state_selected state. (2016.12.10)

  • Solve the above 5.0 Button shadow effect scheme

    In the XML-defined Button, add the following style definition

    style="? android:attr/borderlessButtonStyle"
    Copy the code
  • For the difference between onSingleTapUp and onSIngleTapConfirmed

    The former happens when pressed and lifted, while the latter is triggered when Android has an additional condition that ensures that a click is followed by a short time without a second click. Often used if you need to listen for click and double-click events.

  • How to draw triangles using layer-list

    <layer-list xmlns:android="http://schemas.android.com/apk/res/android"Rotate Android :fromDegrees= rotate Android :fromDegrees="45"
            android:pivotX="85%"
            android:pivotY="135%">
            <shape android:shape="rectangle">
                <size
                    android:width="16dp"
                    android:height="16dp" />
                <solid android:color="#7d72ff"/> </shape> </rotate> </item> // right <item> < Rotate Android :fromDegrees="45"
            android:pivotX="15%"
            android:pivotY="35%">
            <shape android:shape="rectangle">
                <size
                    android:width="16dp"
                    android:height="16dp" />
                <solid android:color="#7d72ff"/> </shape> </rotate> </item> <item> <rotate Android :fromDegrees="45"
            android:pivotX="40%"
            android:pivotY="80%">
            <shape android:shape="rectangle">
                <size
                    android:width="16dp"
                    android:height="16dp"/>
                <solid android:color="#7d72ff"/> </shape> </rotate> </item> // lower <item> < Rotate Android :fromDegrees="45"
            android:pivotX="135%"
            android:pivotY="15%">
            <shape android:shape="rectangle">
                <size
                    android:width="16dp"
                    android:height="16dp"/>
                <solid android:color="#7d72ff"/>
            </shape>
        </rotate>
    </item>
    Copy the code
  • On the property animation rotating View part of the model View flicker solution

    In the quick comment module of Daishen APP information flow, when the quick comment animation was delivered, it was found that the jitter effect achieved by using attribute animation flickered on some models. The dithering effect is implemented through the view.rotation. After research, some models because of hardware acceleration causes. Do the following for the animated View

    view.setLayerType(View.LAYER_TYPE_HARDWARE,null);
    Copy the code
  • Notes under code layout about ConstraintLayout

    Unlike other viewGroups that control the layout of child views, ConstraintLayout needs to build a ConstraintSet object to bind. ConstraintSet#clone(ConstraintLayout ConstraintLayout) to clone the layout information of the existing ConstraintLayout, in the case of manually adding child views. Then the final call to ConstraintSet#applyTo(ConstraintLayout ConstraintLayout) confirms the final layout information.

  • TextView in version 6.0 has single-line tail thumbnail pits

    In the big God information flow, some card information needs to be set to single-line thumbnails. In the process of MTL compatibility test, abnormal display of some models was found. After induction and verification, the version of these models is < 6.0. Text Ellipsize behavior in Android version < 6.0. For this version of the phone, we need to change android:maxLines=”1″ to android:singleLine=”true” when setting a singleLine. Even if the IDE indicates that the API is out of date!

  • EditText automatically gets the solution to the problem caused by focus

    Add foucusable control to its parent control in XML, adding the following properties to intercept the default behavior of EditText

    android:focusable="true"  
    android:focusableInTouchMode="true"
    Copy the code

<< Services >>

  • There is no solution for enabling notifications in Service to disappear after manually cleaning up the application in the background

    From How to remove all notifications when an Android app (activity or service) is killed? Service#onTaskRemoved was a callback to Service after our App was removed. Tried a method can not achieve the effect of clearing.

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        NotificationManager nManager = ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE));
        nManager.cancelAll();
    }
    Copy the code

    In the online application, since our notification is similar to the general order, which has the function of periodic update, we need to completely eliminate all functions carried by serivce. The following method is feasible

     @Override
    public void onTaskRemoved(Intent rootIntent) {
        super.onTaskRemoved(rootIntent);
        stopSelf();
        stopForeground(true);
    }
    Copy the code
  • The global Context uses a more elegant fetching scheme

    Since we are optimizing Application startup time, we are going to remove all static declaration variables from applciation, including the global context variable. We are referring to the leakCanary library, which uses ContentProvider to host the retrieval of the global context, because in the ActivityThread initialization process, ContentProvider#onCreate() is between Application#attachBaseContext(Context) and Application#onCreate(). So the context that we got is valid

    class ContextProvider : ContentProvider() { companion object { private lateinit var mContext: Context private lateinit var mApplication: Application fun getGlobalContext(): Context = mContext fun getGlobalApplication(): Application = mApplication } override fun onCreate(): Boolean { mContext = context!! mContext = context!! .applicationContext as Applicationreturn false} override fun insert(uri: Uri, values: ContentValues?) : Uri? = null override fun query(uri: Uri, projection: Array<out String>? , selection: String? , selectionArgs: Array<out String>? , sortOrder: String?) : Cursor? = null override fun update(uri: Uri, values: ContentValues? , selection: String? , selectionArgs: Array<out String>?) : Int = -1 override fun delete(uri: Uri, selection: String? , selectionArgs: Array<out String>?) : Int = -1 override fun getType(uri: Uri): String? // Manifest declaration <! -- Context provider --> <provider Android :name=".ContextProvider"
            android:authorities="${your_application_id}.contextprovider"
            android:exported="false" />
    Copy the code

<< Threads >>

  • It is recommended that new threads do not call network requests randomly. Generally, newthreads do not have looper queues. Refer to handlerThread

<< Network >>

  • Retorfit Resolution of error in request parameters

    @GET( BASE_URL + "index/login" )
    Observable< LoginResult > requestLogin( @QueryMap(encoded = true) Map< String, String > params );
     
    final Map< String, String > paramsMap = new ParamsProvider.Builder().
            append( "username", account ).
            append( "password",URLEncoded(password) ).
    
    Copy the code

    For login, encode = true indicates that special characters are not URL-encoded, and the default is false.

<< data text >>

  • How to gracefully handle multithreaded read and write problems in SQLite

    • A helper instance corresponds to a DB Connectton, which provides both read and write connections. If only read-only is called, there are also write connections by default.
    • A helper instance can be used across multiple threads, and the Java layer uses a locking mechanism to keep threads synchronized, so that calls to degrees of data are serialized even if there are 100 threads
    • If you try to write to the database from different Connections at the same time, one of them will fail. It doesn’t write the first one and then the second one, and some VERSIONS of SQLite don’t even have an error.

    In general, if you want to use a database in a multithreaded environment, make sure that multiple threads are using the same SQLiteDataBase object, which corresponds to a DB file.

    In particular, if multiple SQliteDatabases open the same DB file and use different threads to write simultaneously (INSERT, update, exexSQL), an exception may occur during SQLiteStatement. Native_execute. This exception comes from a local method that is only protected by a Java lock on SQLiteDataBase. SQLiteCursor does not execute the query immediately, but only loads part of the data as needed, which can be read by multiple threads.

    To deal with the above problem, you can use “one thread writes, multiple threads read simultaneously, each thread uses its own SQLiteOpenHelper.”

    Enable enableWriteAheadLogging on Android 3.0 or later. When turned on, it allows one writer thread to work with multiple readers on an SQLiteDatabase at the same time. The idea is that the write operation is actually in a separate file, not the original database file. Therefore, the write operation does not affect the read operation. The read operation reads the original data file, which is the content before the write operation. After a successful write operation, the changes are merged into the original database file. In this case, the read operation can read the modified content. But this will cost more memory.

  • How to understand the Intent to transfer data appear ` TransactionTooLargeException ` problems

    Intents use binders to transmit data. The data in the Intent is transmitted as objects stored in the Binder transaction buffer for the Parcel. The Binder transaction buffer has a finite fixed size, currently 1MB. Don’t assume that passing less than 1MB of data is safe; the 1MB space is not reserved for the current operation, but is shared by the current process. In other words, intEnts transfer data between activities and are not suitable for transferring too much data by themselves.

    Reference to ali the Android developer’s handbook for data communication between the Activity data is bigger, avoid using Intent + Parcelable, can consider to use alternative, such as the EventBus, avoid TransactionTooLargeException. EventBus uses sticky events to resolve the problem, but Activity rebuilds can get intEnts that EventBus can’t, so it needs to be tailored to the business.

<< Model system Adaptation >>

  • How to solve the problem that the NatigationBar is blocked by the PopupWindow

    popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
    Copy the code
  • How to solve the problem that MIUI system background cannot toast

    Reference github.com/zhitaocai/T… Project, but on mi 3 or Mi Note (4.4.4) phones

    mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    Copy the code

    MContext needs to use ApplicationContext to take effect.

  • How to solve the problem that toast cannot pop up when the notification bar permission is closed

    Since Google sets Toast as the system message right, it can maintain its own message queue by referring to the solution where Android disables the notification message right and fails to pop up Toast.

  • How to adapt vivo and other double-sided screens

    Declare meta-data in androidmanifest.xml

    <meta-data
    android:name="andriod.max_aspect" android:value="ratio_float"/>
    Copy the code

    Alternatively, use Android :maxAspectRatio=”ratio_float”(API LEVEL 26) Ratio_float usually indicates the screen resolution aspect ratio. For other issues such as groove areas and rounded corners cutting, please refer to the vivo open platform documentation corresponding to the latest VIVO models on the market.

  • How do I solve the problem that Huawei devices generate too much broadcast and crash

    In some Huawei applications, if an app registers more than 500 BroadcastReceivers, the “Register too many Broadcast Receivers” exception will be thrown. Through analysis, we found that there is a white list inside the app. We can create a new app and use the wechat package name to test, and we found that there is no such restriction. Just add our package name to the mWhiteList object in the mReceiverResource by reflecting the LoadedApk class. Check out github.com/llew2011/Hu… This project.

  • How can I solve the problem that AdView is not displayed on Huawei devices

    In our project, there used to be a control called “AdView” on the home page to display advertisements. When it was too far, setVisibility(view.gone) was called again on Huawei mobile phone when we setVisibility(). Changing the name of the view later fixes this problem. This problem should be caused by ROM internal through certain rules to determine whether the View in our application is an advertising View and thus forced to hide. So when you write your App’s view related to displaying ads, try to name it as obscure as possible.

  • All kinds of notification bar adaptation scheme

    Refer to the adaptation method implemented by netease Kaola

  • Solve the problem of meizu push content restriction

    Today, I received an alert from Meizu channel that “the pushed content may be too long”. The IM function is targeted at offline device vendors. Meizu push limits title title 1-32 characters and content 1-100 characters. If the notifications frequently exceed the limit, the Meizu push server may not send the notifications to Meizu devices. Therefore, the server limits the message title and content length sent to meizu server.

  • Solve the problem that the application starts after the system is installed and the Launcher starts repeatedly after the Home is hidden

    Check whether the startup page is the root node (recommended)

    if(! isTaskRoot()){ finish();return 
    }
    Copy the code

    FLAG_ACTIVITY_BROUGHT_TO_FRONT or not FLAG_ACTIVITY_BROUGHT_TO_FRONT

    if((getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) ! = 0) { finish();return;
    }
    Copy the code
  • For an application with launcher as an Activity, you will receive notifications from a third party (Xiaomi, Huawei, Meizu) or share it when it is not started at all

    Since our app LauncherActivity is used to distribute portals to different scenes, logic A goes to the special scene page A and logic B goes to the main page B.

    • In onCreate, the intent is intercepted to determine the pull parameter. If there is a pull parameter, the intent is delivered to the main page B for processing
    • In some scenarios, such as third-party message push, Huawei and Xiaomi cannot distinguish a launcher or a launcher intent. For this purpose, the logic of entering the launcher or launcher screen is limited, and the main page of the rest of the scenarios is B
    if(Whether the backend control needs to enter the special scene page) {Boolean goToA =false;
        if(getIntent() ! = null) { String action = getIntent().getAction(); Set<String> category = getIntent().getCategories();if (TextUtils.equals(action, "android.intent.action.MAIN")) {
                if(category ! = null && category.contains("android.intent.category.LAUNCHER"Intent Intent = new Intent(this, page a.class); intent.setData(getIntent().getData()); startActivity(intent); goToA =true; }}}if(! goToA) { goToMainActivity(); }}else {
        goToMainActivity();
    }
    Copy the code
  • The scene judgment analysis under the multi-scene pull up scenario of App

    Refer to my other article for a summary of my thinking about online project pull-up scenarios

  • 8.0 ROM Only fullscreen Opaque Activities can request orientation solution

    Due to our project need to deal with immersion, so for android: windowIsTranslucent properties opened by default. However, some 8.0 devices appeared weird crash online, because we unified the orientation statement of the page into portrait. A review of the Android source code update found that the two logic in the 8.0 source code was incompatible, which was later fixed by Google after the 8.0 version. But the domestic ROM doesn’t seem to fix the problem. Colleagues behind provides a more opportunistic, through for the page to specify the android: screenOrientation = “behind” to avoid the problem of version 8.0 at the same time, compatible with all the android version.

  • 9.0 Android Support for Plaintext Connections (Http)

    Android 9 (API level 28) starts with plaintext support disabled by default

    <? xml version="1.0" encoding="utf-8"? > <manifest ... > <uses-permission android:name="android.permission.INTERNET" />
        <application
            ...
            android:usesCleartextTraffic="true". >... </application> </manifest>Copy the code
  • 10.0 Solution to obtaining IMEI Exception

    I am Getting IMEI NULL in Android Q

    The device identifier indicates that the IMEI and serial number available from READ_PHONE_STATE are no longer supported. Unless your App is ROM set as a system level App.

    Google has provided unique identifier best practices, but this scheme is applicable to limited scenarios. The best approach is to implement your own device identification scheme using UUID.

    Check out the Android Q Adaptation guide to save you a lot of detours.

    public static String getUUID() {
    String serial = null;
    String m_szDevIDShort = "35" +
        Build.BOARD.length() % 10 + Build.BRAND.length() % 10 +
        Build.CPU_ABI.length() % 10 + Build.DEVICE.length() % 10 +
        Build.DISPLAY.length() % 10 + Build.HOST.length() % 10 +
        Build.ID.length() % 10 + Build.MANUFACTURER.length() % 10 +
        Build.MODEL.length() % 10 + Build.PRODUCT.length() % 10 +
        Build.TAGS.length() % 10 + Build.TYPE.length() % 10 +
        Build.USER.length() % 10; //13 位
    
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        serial = android.os.Build.getSerial();
        } else{ serial = Build.SERIAL; } //API>=9 use serial numberreturnnew UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString(); } catch (Exception Exception) {// Serial requires an initialization for serial ="serial"; } // A 15-digit number cobbled together using hardware informationreturn new UUID(m_szDevIDShort.hashCode(), serial.hashCode()).toString();
    }
    Copy the code

<< Build >>

  • Travis – Ci higher version of androidO compilation encountered a license failed compilation solution

    See CI discussion to add dist: Precise and add the sdkManager directive to the before_Install TAB. Please refer to my open source project configuration for details

  • The Android version supported by Dalvik has some limitations on subcontracting execution

    • The dex file must be installed during cold startup. If the dex file is too large, the processing time may be too long, resulting in ANR
    • Even if multiDex is used on systems lower than 4.0, the bug of Dalvik linearAlloc may occur. This is because the multiDex requires a large amount of memory, which may cause the program to crash at runtime. This limit is an improvement on 4.0, but can still be triggered on machines below 5.0.
  • Dalvik subcontract to build the possible Java. Each dex file lang. NoClassDefFoundError

    The reason for this problem is that the build tool makes a complex decision to draw lines to determine which classes are needed in the main DEX file so that the application can start properly. The above exception is thrown if any classes required during startup are not found in the main dex. All must declare them in the multiDexKeepFile or multiDexKeepProguard property, manually specifying these classes as required in the main dex file.

    Create multidex-new. TXT and write the following new classes

    com/example/Main2.class
    com/example/Main3.class
    Copy the code

    Create meltidex-new.pro and write the following keep class

    -keep class com.example.Main2
    -keep class com.example.Main3
    Copy the code

    The above files are then declared in the Gradle multiDexKeepFile and multiDexKeepProguard properties

    android {
    buildTypes {
        release {
            multiDexKeepFile file 'multidex-new.txt'
            multiDexKeepProguard 'multidex-new.pro'. }}}Copy the code
  • Java 8 methods of java.lang.Long and java.lang.Character are not desugared by D8

    This problem occurs when compiling with Kotlin, infering the JVM target from the Java version in ndroid.compileOptions from Kotlin1.3.30, If both sourceCompatibility and targetCompatibility are set, select “1.8” to that or higher. You can solve this problem by specifying JavUncomfortable 1.6.

    sourceCompatibility JavaVersion.VERSION_1_6
    targetCompatibility JavaVersion.VERSION_1_6
    Copy the code

    The Issue indicates that AGP (Android Gradle Plugin) 3.4 has solved the problem of desugarization, and can be upgraded to solve it.

  • FindBinding vs getBinding scenarios in Databinding

    The difference is that findBinding traverses the parent node, whereas getBinding returns null if the view is not the same as the node.

  • Gradle sync failed: Cannot choose between the following configurations of project

    See the answers to issues

    If you’re using Android plugin for Gradle 3.0.0 or higher, the plugin automatically matches each variant of your app with corresponding variants of its local library module dependencies for you. That is, you should no longer target specific variants of local module dependencies, show as below

     dependencies {
    // Adds the 'debug' varaint of the library to the debug varaint of the app
    debugCompile project(path: ':my-library-module', configuration: 'debug')
    
    // Adds the 'release' varaint of the library to the release varaint of the app
    releaseCompile project(path: ':my-library-module', configuration: 'release')}Copy the code
  • Gradle configures local offline packages

    1. Offline Download Gradle offline packages are stored in urls
    2. Modify thegradle/wrapper/gradle-wrapper.propertiesAdjust thedistributionUrlDirectory pointing to URL
    3. Modify thebuild.gradleClasspath version maps Gradle version
  • Fixed segmentation and whitespace in KVM/JVM -classpath compilation

    On Linux/MAC OS, use: to split multiple CLASspath paths. On Windows, use;. Segmentation.

    If there is a space in the Linux/MAC OS path, avoid it temporarily. =.

  • Databinding NoSuchMethodError with buildTool 3.4.0

    After upgrading the project from Gradle 3.1 to 3.4.0 and using AndroidX, the compilation failed. The project is using databinding and the compilation appears

    java.lang.NoSuchMethodError: No direct method <init> (Landroidx/databinding/DataBindingComponent; Landroid/view/View; I)Vin 
    class Landroidx/databinding/ViewDataBinding; or its super classes
    (declaration of 'androidx.databinding.ViewDataBinding'
    Copy the code

    The aar library is compiled with the old gradle version, and the new gradle is updated. Lead to the old ViewDataBinding constructor signatures can’t match the new androidx. Databinding. ViewDataBinding signature.

    // Older version protected ViewDataBinding(DataBindingComponent bindingComponent, View root, intlocalProtected ViewDataBinding(Object bindingComponent, View root, intlocalFieldCount)
    Copy the code

    Fortunately, 3.4.1 has been fixed. Just change 3.4.0 -> 3.4.1.

  • The debugging message debug info can be unavailabe is displayed

    When you use AS to connect to the huawei real machine for debugging, the IDE always displays Warning: debug info can be unavailable. Please close other application using ADB: Restart ADB integration and try again. Restart ADB numerous times and shut down in addition to IDE accident may be connected to ADB software are invalid, and finally restart the real machine to solve. The reason is an ADB connection problem, because sometimes ADB caches an invalid connection on a real/virtual device and cannot connect to the device because the connection is busy.

  • Project agent on Mac to clear gradle cache

    Sometimes a project declares a proxy or an AS configures a proxy before clearing it. It still runs to the agent when it finds a project run. The reason is that the local gradle directory also caches a proxy information. You need to delete it completely.

    MAC: ~ /. Gradle/gradle. Delete the properties corresponding to the agent for the information. Other OSS: Please refer to this idea to find corresponding files to deleteCopy the code

<< Version Control >>

  • Git modifies the commit record

    Git reset --soft HEAD^ Undo the current commit, if only to modify the prompt, use git commit --amendCopy the code
  • Git ignore does not take effect

    git rm -r --cached .
    git add .
    git commit -m 'update .gitignore'
    Copy the code

Other < < > >

  • After the ExoPlayer answers the call, the mute status of the original set Source will disappear, and the video may suddenly sound when the app is returned to resume

    The reason is that the playback volume is charged after the multimedia focus is snatched by the call. For the solution, see github.com/google/ExoP…

  • Please select Android SDK

    Modify Build Tools version in File->Project Structure

  • About Java character and byte encoding relationship understanding

        // 1
        Log.d("Encoding Test - Characters"."a".length.toString())
        // 1
        Log.d("Encoding Test - Characters"."Test".length.toString())
        // 5
        Log.d("Encoding Test - Characters"."Test ABC".length.toString())
    
        // 1
        Log.d("Encoding Test -UTF_8"."a".toByteArray(Charsets.UTF_8).size.toString())
        // 3
        Log.d("Encoding Test -UTF_8"."Test".tobytearray (Charsets.utf_8).sie.tostring ()) // 9, UTF_8 supports encoding with 1, 2, 3, and 4 bytes, one Chinese byte is 3 bytes, one English byte is 1 byte log.d (Charsets.utf_8).size."Encoding Test -UTF_8"."Test ABC".toByteArray(Charsets.UTF_8).size.toString())
    
        // 1
        Log.d("Encoding test -US_ASCII"."a".toByteArray(Charsets.US_ASCII).size.toString())
        // 1
        Log.d("Encoding test -US_ASCII"."Test"ToByteArray (Charsets. US_ASCII). The size. The toString ()) / / 5, a Chinese accounts for 1 byte, an English accounts for 1 byte the d ("Encoding test -US_ASCII"."Test ABC".toByteArray(Charsets.US_ASCII).size.toString())
    
        // 1
        Log.d("Coding Test -ISO_8859_1"."a".toByteArray(Charsets.ISO_8859_1).size.toString())
        // 1
        Log.d("Coding Test -ISO_8859_1"."Test".tobytearray (Charsets.iso_8859_1).sie.tostring ()) // 5, 1 Chinese 1 byte, 1 English 1 byte log.d (Charsets.iso_8859_1).size."Coding Test -ISO_8859_1"."Test ABC".tobytearray (Charsets.iso_8859_1).sie.tostring ()) // 4, there is a proxy pair +2 bytes log.d ("Encoding Test -UTF_16"."a".tobytearray (Charsets.utf_16).sie.tostring ()) // 4, there is a proxy pair +2 bytes log.d ("Encoding Test -UTF_16"."Test".tobytearray (Charsets.utf_16).sie.tostring ()) // 12, UTF_16 only supports 2 or 4 bytes encoding, one Chinese two bytes and one English two bytes log.d (Charsets.utf_16).size."Encoding Test -UTF_16"."Test ABC".toByteArray(Charsets.UTF_16).size.toString())
    
        // 2
        Log.d("Encoding Test -UTF_16BE"."a".toByteArray(Charsets.UTF_16BE).size.toString())
        // 2
        Log.d("Encoding Test -UTF_16BE"."Test"ToByteArray (Charsets. UTF_16BE). The size. The toString ()) / / 10, a Chinese account for 2 bytes, an English accounts for 2 bytes Log. D ("Encoding Test -UTF_16BE"."Test ABC".toByteArray(Charsets.UTF_16BE).size.toString())
    
        // 2
        Log.d("Encoding Test -UTF_16LE"."a".toByteArray(Charsets.UTF_16LE).size.toString())
        // 2
        Log.d("Encoding Test -UTF_16LE"."Test"ToByteArray (Charsets. UTF_16LE). The size. The toString ()) / / 10, a Chinese account for 2 bytes, an English accounts for 2 bytes Log. D ("Encoding Test -UTF_16LE"."Test ABC".toByteArray(Charsets.UTF_16LE).size.toString())
    
    
        // 8
        Log.d("Encoding Test -UTF_32"."a".toByteArray(Charsets.UTF_32).size.toString())
        // 8
        Log.d("Encoding Test -UTF_32"."Test".tobytearray (Charsets.utf_32).size.tostring ()) // 24 UTF-32 supports 4-byte encoding, which is the same as UTF-16 principle. One Chinese byte is 4 bytes, and one English byte is 4 bytes."Encoding Test -UTF_32"."Test ABC".toByteArray(Charsets.UTF_32).size.toString())
    
        // 4
        Log.d("Encoding Test -UTF_32LE"."a".toByteArray(Charsets.UTF_32LE).size.toString())
        // 4
        Log.d("Encoding Test -UTF_32LE"."Test".tobytearray (Charsets.utf_32le).size.tostring ()) //20, a Chinese 4 bytes, a English 4 bytes log.d ("Encoding Test -UTF_32LE"."Test ABC".toByteArray(Charsets.UTF_32LE).size.toString())
    
        // 4
        Log.d("Encoding Test -UTF_32BE"."a".toByteArray(Charsets.UTF_32BE).size.toString())
        // 4
        Log.d("Encoding Test -UTF_32BE"."Test".tobytearray (Charsets.utf_32be).size.tostring ()) // 20, a Chinese 4 bytes, a English 4 bytes log.d ("Encoding Test -UTF_32BE"."Test ABC".toByteArray(Charsets.UTF_32BE).size.toString())
    Copy the code
  • On the length calculation of emoji code

    Focus on getting familiar with the split logic of multi-plane emoji under the emoji identified by Unicode coding. Refer to this article

  • Do not use System.CurrentTimemillis () as a time log for business scenarios

    In our business code, “In order to prevent a page from being entered repeatedly in a short time, system.currentTimemillis () was used to record the time when the page was entered last time”. As a result, after a user changed the System time, he found that he could not enter the page for a second time. The reason was that the change of the System time caused a huge error in the difference between system.currentTimemillis () and the time recorded last time. Therefore, the following methods are recommended.

    SystemClock.elapsedRealtime(); // Don't use system.currentTimemillis ()Copy the code

    For more details, see Don’t Use System.currentTimemillis () for Time Interval

For more detailed interview experiences, please refer to the interviews I have experienced over the years | written for fresh graduates and job seekers in the context of COVID-19.