A magical tool for picking up girls, creating Christmas snowflake special effects, additional online hot fixes

A magical tool for picking up girls, creating Christmas snowflake special effects, additional online hot fixes

I believe that those who opened Taobao on their mobile phones last Christmas will remember the special effects at that time: snow fell all over the screen, and there was a little snowman next to it to control the background music of the music box, which made people feel as if they were in the scene, and even couldn't help but want to shop hard (wrong). It was probably like this:

Well, it's really cool, so let's analyze how it is achieved step by step:

1. Implementing the Snow View

First of all, the full-screen snowflakes on the top layer are most likely a top-level View, and this View is controlled by dynamic loading (this effect can be seen without updating Taobao). So we must first implement the View with the snowflake effect. Life is short, so use it as it comes. Open gank.io and search for "snowflakes":

It seems that the 7th library is what we want. Click into the source code and download it directly. Remember to star it to support the author. Now we have a complete snow effect View in our project.

2. Implement the Snowman Player View

This can be achieved with a snowman picture + a button, so I won't explain it in detail. Next, we need a Christmas audio clip, and directly playing the audio clip online is undoubtedly a good solution to save space. The lonely and sweet atmosphere created by "My Skateboard Shoes" is undoubtedly the most suitable for Christmas, so we got a "divine song" URL:

http://cdn.ifancc.com/TomaToDo/bgms/my_hbx.mp3

Next, we need to find a picture of a snowman as the background of the player, so Armstrong... No, it's this:

[[179119]]

Well, it's quite cute and festive. The core code of the player is as follows:

  1. package com.kot32.christmasview.player;
  2.  
  3. import android.content.Context;
  4. import android.media.AudioManager;
  5. import android.media.MediaPlayer;
  6. import android.util.AttributeSet;
  7. import android. view . View ;
  8. import android.widget.Toast;
  9.  
  10. import com.kot32.christmasview.R;
  11.  
  12. import java.io.IOException;
  13.  
  14. /**
  15. * Created by kot32 on 16/12/8.
  16. */
  17. public class MyPlayer extends View {
  18.  
  19. public MediaPlayer mediaPlayer;
  20.  
  21. public MyPlayer(Context context) {
  22. super(context);
  23. init();
  24. }
  25.  
  26. public MyPlayer(Context context, AttributeSet attrs) {
  27. super(context, attrs);
  28. init();
  29. }
  30.  
  31. private void init() {
  32. setBackgroundResource(R.drawable.pig);
  33. mediaPlayer = new MediaPlayer();
  34. mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
  35. playUrl( "http://172.20.248.106/IXC5b415fcacfc3c439e25a3e74533d2239/TomaToDo/bgms/my_hbx.mp3" );
  36. Toast.makeText(getContext(), "Start playing" , Toast.LENGTH_SHORT).show();
  37. setOnClickListener(new OnClickListener() {
  38. @Override
  39. public void onClick( View v) {
  40. if (!mediaPlayer.isPlaying()) {
  41. mediaPlayer.start();
  42. Toast.makeText(getContext(), "Continue playing" , Toast.LENGTH_SHORT).show();
  43. } else {
  44. mediaPlayer.pause();
  45. Toast.makeText(getContext(), "Pause playback" , Toast.LENGTH_SHORT).show();
  46. }
  47. }
  48. });
  49. }
  50.  
  51. public void playUrl(String videoUrl) {
  52. try {
  53. mediaPlayer.reset();
  54. mediaPlayer.setDataSource(videoUrl);
  55. mediaPlayer.prepare (); // Automatically play after prepare
  56. mediaPlayer.start();
  57. } catch (IllegalArgumentException e) {
  58. e.printStackTrace();
  59. } catch (IllegalStateException e) {
  60. e.printStackTrace();
  61. } catch (IOException e) {
  62. e.printStackTrace();
  63. }
  64. }
  65.  
  66. @Override
  67. protected void onDetachedFromWindow() {
  68. super.onDetachedFromWindow();
  69. try {
  70. media

3. Dynamic loading ideas

The above basically realizes the local snowflake and music playing effects. So how to dynamically load these two Views into the main program without updating the main program?

First of all, we understand that Android's DexClassloader has the ability to load any class in any APK, but there are the following limitations:

  • Since the loaded Activity is not declared in the host Manifest file, the framework cannot find and initialize the Activity.
  • The loaded Activity does not have a life cycle for the same reason as above.
  • The Resource file id of the loaded class will be mixed with the main program.

Since we are only loading the View, not the entire Activity, the first two problems will not be encountered, and the third problem can be solved.

We also need to do these three things in the main program:

  • Leave space for the ViewGroup that can load the View
  • To get the updated patch package
  • After loading the View from the apk package, put it into the reserved ViewGroup. In this way, you can load the active View online not only on Christmas but also in various subsequent activities.

4. Start loading

Before loading the View, we must first realize that this View references image resources (pig images), so we need to solve the resource problem:

  1. private void initResource() {
  2. Resources resources = getContext().getResources();
  3. try {
  4. AssetManager newManager = AssetManager.class.newInstance();
  5. Method addAssetPath = newManager.getClass().getMethod( "addAssetPath" , String.class);
  6. addAssetPath.invoke(newManager, DynamicViewManager.getInstance().getUpdateFileFullPath());
  7. Resources newResources = new Resources(newManager,
  8. resources.getDisplayMetrics(), resources.getConfiguration());
  9. Reflect.onObject(getContext()). set ( "mResources" , newResources);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }

The purpose of the above code is to assign the resource manager with the external update package path added to the original resource manager of the App, which means that the plug-in resources can now be accessed in the host.

The core loading code is as follows:

  1. DexClassLoader classLoader = new DexClassLoader(apkFile.getAbsolutePath()
  2. , "dex_out_put_dir"  
  3. , null  
  4. , getClass().getClassLoader());
  5. Class newViewClazz = classLoader.loadClass( "view's package name" );
  6. Constructor con = newViewClazz.getConstructor(Context.class);
  7. // first use Activity's Resource lie to   View  
  8. if (dynamicView == null ) {
  9. dynamicView = ( View ) con.newInstance(getContext());
  10. }
  11. // Replace the View 's mResources and recover the Activity's avoid disorder of Resources
  12. Reflect.onObject(getContext()). set ( "mResources" , null );
  13. getContext().getResources();
  14.  
  15. RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(DisplayUtil.dip2px(getContext(), viewInfo.layoutParams.width),
  16. DisplayUtil.dip2px(getContext(), viewInfo.layoutParams.height));
  17. layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout. TRUE );
  18. addView(dynamicView, layoutParams);

The purpose of the operation on mResources in the middle is to reset the mResources of the host Activity to avoid conflicts with plug-ins when using resources in the Activity.

However, I have cleverly packaged the update package download, version management, and dynamic loading, so the correct way to load is:

Refer to it: https://github.com/kot32go/dynamic-load-view

Then:

1.Host declaration:

  1. <RelativeLayout
  2. xmlns:android= "http://schemas.android.com/apk/res/android"  
  3. xmlns:app= "http://schemas.android.com/apk/res-auto"  
  4. android:layout_width= "match_parent"  
  5. android:layout_height= "match_parent"  
  6. android:background= "@drawable/tb_bg"  
  7. >
  8.  
  9. <com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup
  10. android:layout_width= "match_parent"  
  11. android:layout_height= "match_parent"  
  12. app:uuid= "activity_frame" >
  13.  
  14. <TextView
  15. android:layout_width= "wrap_content"  
  16. android:layout_height= "wrap_content"  
  17. android:text= "Original page"  
  18. />
  19.  
  20. </com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup>
  21.  
  22. <com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup
  23. android:layout_width= "60dp"  
  24. android:layout_height= "60dp"  
  25. android:layout_alignParentRight= "true"  
  26. android:layout_centerVertical= "true"  
  27. app:uuid= "activity_player" >
  28.  
  29. </com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup>
  30.  
  31.  
  32. </RelativeLayout>

The above declares the layout of the main interface. Of course, before dynamic loading, there will be nothing except the original "original page" TextView, that is, the program before Christmas. Note: The uuid will match the online package.

2. Install the plugin package

In fact, it is to package the program that contains the two Views (snowflake and snowman) we wrote before into an apk. It is not necessary to sign it.

3. Put the plug-in package on the server

Declare the plugin package address and some parameters of the dynamic View in the JSON returned by the server. The request address of the demonstration program here is:

http://tomatodo.ifancc.com/php/dynamicView.php

The return value is:

  1. {
  2. "version" : 54,
  3. "downLoadPath" : "http://obfgb7oet.bkt.clouddn.com/patch106.apk" ,
  4. "fileName" : "patch106.apk" ,
  5. "viewInfo" : [
  6. {
  7. "packageName" : "com.kot32.testdynamicviewproject.snow.widgets.SnowingView" ,
  8. "uuid" : "activity_frame" ,
  9. "layoutParams" : {
  10. "width" : -1,
  11. "height" : -1
  12. } },
  13. {
  14. "packageName" : "com.kot32.testdynamicviewproject.player.MyPlayer" ,
  15. "uuid" : "activity_player" ,
  16. "layoutParams" : {
  17. "width" : -1,
  18. "height" : -1
  19. } }
  20. ]}

We declare the version of the online package, the package name and layout parameters of each View, and most importantly, the uuid that is aligned with the declaration in the host program.

In addition, Dynamic-load-view can dynamically load Views and resources in external apk, hot-fix online Views, and perform modular updates.

Screenshots

Features

  • Plug-ins are completely independent of the host.
  • Use View as a module for modular development and update.
  • You can also fill the entire Activity with View, which is equivalent to updating the Activity.
  • There are few side effects and there are no life cycle issues caused by loading the Activity.
  • Good compatibility. No problem with Android 4.0~6.0.
  • Simple. The core code does not exceed 400 lines. You can download the source code and modify the update rules yourself.

How to use

  • Download the library and reference it as a library.
  • It needs to be initialized in the onCreate of the host program's Application. The code is as follows:
  1. DynamicViewConfig config = new DynamicViewConfig.Builder()
  2. .context(this)
  3. .getUpdateInfoApi( "http://vpscn.ifancc.com/php/dynamicView.php" )
  4. .build();
  5. DynamicViewManager.getInstance(config).init();

The getUpdateInfoApi method needs to pass in an API address, which provides updated information to the client. In the above address, the server returns the following JSON string:

  1. {
  2. "version" : 39,
  3. "downLoadPath" : "http://obfgb7oet.bkt.clouddn.com/patch101.apk" ,
  4. "fileName" : "patch101.apk" ,
  5. "viewInfo" : [
  6. {
  7. "packageName" : "com.kot32.testdynamicviewproject.MyButton" ,
  8. "uuid" : "test" ,
  9. "layoutParams" : {
  10. "width" : 100,
  11. "height" : 100
  12. }
  13. },
  14. {
  15. "packageName" : "com.kot32.testdynamicviewproject.MyButton1" ,
  16. "uuid" : "test_activity" ,
  17. "layoutParams" : {
  18. "width" : -1,
  19. "height" : -1
  20. }
  21. }
  22. ]
  23. }

The JSON string above defines the updated version and the address of the update package, and provides detailed update information for each View.

packageName : The full package name of the View in the plugin APK.

uuid : The same UUID as the View to be updated in the host application.

layoutParams: layout parameters.

You can also modify the parameters that the server needs to provide by changing the model class in the com.kot32.dynamicloadviewlibrary.model package.

  • The View to be updated needs to be declared as follows in the xml layout file. Note that the uuid attribute must be assigned a value. When updating, the View with the same uuid will be matched.
  1. <com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup
  2. android:id= "@+id/dv"  
  3. android:layout_width= "200dp"  
  4. android:layout_height= "200dp"  
  5. app:uuid= "test"  
  6. android:layout_centerInParent= "true" >
  7.  
  8. <! --default view -->  
  9. <ImageView
  10. android:layout_width= "match_parent"  
  11. android:layout_height= "match_parent"  
  12. android:src= "@mipmap/ic_launcher" />
  13.  
  14. </com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup>

For plug-ins, you only need to define the View and then directly package it into an APK package.

For more detailed information, please download the sample source code directly. The source code is not much and is easy to understand.

defect

  • Now you can load string and drawable resources in the plug-in, but there are still some problems with the loading of style.xml and dimens.xml.
  • It is best not to duplicate the names of resource files in the plug-in program with those in the main program.
  • To access resources in a plugin, use: getContext().getResources()

<<:  How to make your product stand out in the Apple App Store in 2017?

>>:  Implement national strategies and “supply” opportunities for the development of integrated national big data centers

Recommend

From 0 to professional event operation

For friends who are engaged in event operations ,...

The 10 most common questions for beginners learning SEO

Before reading this article, novice SEOs can revi...

How much does it cost to develop a building materials mini program in Bozhou?

How much does it cost to join the building materi...

How to use TikTok to acquire 300,000 customers?

In this article, let’s take a look at how to use ...

Why iOS consumes more power when background apps are turned off manually?

Android phone users should have a habit: when the...

5 Tips for Using Tik Tok to Master Film and Television Marketing!

Since Tik Tok became popular, there is another ne...

How to create a bidding page for Baidu bidding?

No matter how difficult it is to make a bidding s...