Android中利用動態載入實現手機淘寶的節日特效_Android

來源:互聯網
上載者:User

相信去年聖誕節開啟過手機淘寶的童鞋都會對當時的特效記憶猶新吧:全屏飄雪,旁邊還有個小雪人來控制八音盒背景音樂的播放,讓人有種身臨其境的感覺,甚至忍不住想狠狠購物了呢(誤),大概就是下面這個樣子滴:


嗯,確實很炫,那麼我們一步步去分析是如何?的:

一、實現下雪的 View

首先,最上面一層的全屏雪花極有可能是一個頂層的View,而這個View是通過動態載入去控制顯示的(不更新淘寶也能看到這個效果)。那麼我們先得實現雪花效果的 View,人生苦短,拿來就用。開啟 gank.io,搜尋"雪花":

看樣子第7個庫就是我們想要的了,點進源碼,直接 download 不解釋,記得 star 一個支援作者。那麼現在我們的項目中就有一個完整的下雪效果 View 了。

二、實現雪人播放器 View

這個一張雪人圖片+一個按鈕即可實現,就不多解釋了。接下來需要一段聖誕節音頻,直接進行線上音頻播放無疑是節省空間的好方案。『我的滑板鞋』烘托出的寂寞而甜蜜的氛圍無疑是最適合聖誕節的,因此我們得到了『神曲』URL 一枚:
http://cdn.ifancc.com/TomaToDo/bgms/my_hbx.mp3

接下來要找一個小雪人的圖片當作播放器的背景,那麼阿姆斯特朗...不對,是這個:

嗯,相當可愛喜慶。那麼播放器核心代碼如下:

package com.kot32.christmasview.player;import android.content.Context;import android.media.AudioManager;import android.media.MediaPlayer;import android.util.AttributeSet;import android.view.View;import android.widget.Toast;import com.kot32.christmasview.R;import java.io.IOException;/** * Created by kot32 on 16/12/8. */public class MyPlayer extends View { public MediaPlayer mediaPlayer; public MyPlayer(Context context) {  super(context);  init(); } public MyPlayer(Context context, AttributeSet attrs) {  super(context, attrs);  init(); } private void init() {  setBackgroundResource(R.drawable.pig);  mediaPlayer = new MediaPlayer();  mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  playUrl("http://172.20.248.106/IXC5b415fcacfc3c439e25a3e74533d2239/TomaToDo/bgms/my_hbx.mp3");  Toast.makeText(getContext(), "開始播放", Toast.LENGTH_SHORT).show();  setOnClickListener(new OnClickListener() {   @Override   public void onClick(View v) {    if (!mediaPlayer.isPlaying()) {     mediaPlayer.start();     Toast.makeText(getContext(), "繼續播放", Toast.LENGTH_SHORT).show();    } else {     mediaPlayer.pause();     Toast.makeText(getContext(), "暫停播放", Toast.LENGTH_SHORT).show();    }   }  }); } public void playUrl(String videoUrl) {  try {   mediaPlayer.reset();   mediaPlayer.setDataSource(videoUrl);   mediaPlayer.prepare();//prepare之後自動播放   mediaPlayer.start();  } catch (IllegalArgumentException e) {   e.printStackTrace();  } catch (IllegalStateException e) {   e.printStackTrace();  } catch (IOException e) {   e.printStackTrace();  } } @Override protected void onDetachedFromWindow() {  super.onDetachedFromWindow();  try {   mediaPlayer.stop();   mediaPlayer.release();  }catch (Exception e){   e.printStackTrace();  } }}

三、動態載入思路

上面基本實現了在本地的雪花以及播放音樂效果,那麼在不更新主程式的情況下,如何將這兩個View動態載入到主程式當中去呢?

首先我們明白,Android 的DexClassloader 是擁有載入任意APK 中任意類的能力的,只是有以下限制:

載入出的Activity 由於不在宿主 Manifest 檔案中聲明,因此架構無法找到並初始化這個Activity。

載入出的Activity 不具備生命週期,理由同上。

載入出的類的Resource 檔案id 會和主程式混淆在一起。

由於我們只是載入View,並不是載入整個Activity,所以前兩個問題並不會遇到,而第三個問題可以想辦法解決掉。

在主程式中我們也要做這三件事:

把能夠裝載View的ViewGroup 的空位留出來

去擷取更新的patch包

把View 從apk包中載入出來之後,放進留好的ViewGroup 中。

這樣一來,不僅是聖誕節,在之後的各種活動上都可以線上去載入活動的View。

四、開始載入

在載入View 之前,首先要意識到這個View 是引用了圖片資源的(小豬圖片),因此我們要解決資源問題:

private void initResource() {  Resources resources = getContext().getResources();  try {   AssetManager newManager = AssetManager.class.newInstance();   Method addAssetPath = newManager.getClass().getMethod("addAssetPath", String.class);   addAssetPath.invoke(newManager, DynamicViewManager.getInstance().getUpdateFileFullPath());   Resources newResources = new Resources(newManager,     resources.getDisplayMetrics(), resources.getConfiguration());   Reflect.onObject(getContext()).set("mResources", newResources);  } catch (Exception e) {   e.printStackTrace();  } }

上面代碼的作用是:把添加了外部更新包路徑的資源管理員賦值給了App原來的資源管理員,也就是說現在可以在宿主中訪問外掛程式資源了。

核心載入代碼如下:

DexClassLoader classLoader = new DexClassLoader(apkFile.getAbsolutePath()     , "dex_out_put_dir"     , null     , getClass().getClassLoader());Class newViewClazz = classLoader.loadClass("view's package name");Constructor con = newViewClazz.getConstructor(Context.class);//first use Activity's Resource lie to Viewif (dynamicView == null) { dynamicView = (View) con.newInstance(getContext());}//Replace the View's mResources and recovery the Activity's avoid disorder of ResourcesReflect.onObject(getContext()).set("mResources", null);getContext().getResources();RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(DisplayUtil.dip2px(getContext(), viewInfo.layoutParams.width),   DisplayUtil.dip2px(getContext(), viewInfo.layoutParams.height));layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);addView(dynamicView, layoutParams);

中間對 mResources 的操作的作用是:將宿主的Activity 的mResources 重設,避免在Activity 中使用資源時和外掛程式衝突。

然而機智的我已經把更新包下載、版本管理、動態載入都封裝好了,所以正確的載入方式是:

引用它:https://github.com/kot32go/dynamic-load-view

然後:

1.宿主聲明:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/tb_bg" > <com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup  android:layout_width="match_parent"  android:layout_height="match_parent"  app:uuid="activity_frame">  <TextView   android:layout_width="wrap_content"   android:layout_height="wrap_content"   android:text="原始頁面"   /> </com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup> <com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup  android:layout_width="60dp"  android:layout_height="60dp"  android:layout_alignParentRight="true"  android:layout_centerVertical="true"  app:uuid="activity_player"> </com.kot32.dynamicloadviewlibrary.core.DynamicViewGroup></RelativeLayout>

以上聲明了主介面的布局,當然,在動態載入之前除了原有的"原始頁面"TextView,是不會有任何其他東西的,也就是聖誕節來臨之前的程式。注意:uuid 會和線上包相匹配。

2.打外掛程式包

其實就是把之前包含了我們所寫的兩個View(雪花和雪人)的程式打包成apk。可以不簽名。

3.把外掛程式包放到伺服器

在伺服器返回的JSON中聲明外掛程式包地址和動態View 的一些參數,這裡的示範程式請求地址為:

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

傳回值為:

{ "version": 54, "downLoadPath": "http://obfgb7oet.bkt.clouddn.com/patch106.apk", "fileName": "patch106.apk", "viewInfo": [ {  "packageName": "com.kot32.testdynamicviewproject.snow.widgets.SnowingView",  "uuid": "activity_frame",  "layoutParams": {  "width": -1,  "height": -1  } }, {  "packageName": "com.kot32.testdynamicviewproject.player.MyPlayer",  "uuid": "activity_player",  "layoutParams": {  "width": -1,  "height": -1  } } ]}

我們聲明了這次線上包的版本,每個View 的包名和布局參數, 以及最重要的 和宿主程式中聲明對齊的uuid。

以上所述是小編給大家介紹的Android中利用動態載入實現手機淘寶的節日特效,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.