欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android中利用動(dòng)態(tài)加載實(shí)現(xiàn)手機(jī)淘寶的節(jié)日特效

 更新時(shí)間:2016年12月19日 14:00:44   作者:kot32go  
這篇文章主要介紹了Android中利用動(dòng)態(tài)加載實(shí)現(xiàn)手機(jī)淘寶的節(jié)日特效,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

相信去年圣誕節(jié)打開(kāi)過(guò)手機(jī)淘寶的童鞋都會(huì)對(duì)當(dāng)時(shí)的特效記憶猶新吧:全屏飄雪,旁邊還有個(gè)小雪人來(lái)控制八音盒背景音樂(lè)的播放,讓人有種身臨其境的感覺(jué),甚至忍不住想狠狠購(gòu)物了呢(誤),大概就是下面這個(gè)樣子滴:


嗯,確實(shí)很炫,那么我們一步步去分析是如何實(shí)現(xiàn)的:

一、實(shí)現(xiàn)下雪的 View

首先,最上面一層的全屏雪花極有可能是一個(gè)頂層的View,而這個(gè)View是通過(guò)動(dòng)態(tài)加載去控制顯示的(不更新淘寶也能看到這個(gè)效果)。那么我們先得實(shí)現(xiàn)雪花效果的 View,人生苦短,拿來(lái)就用。打開(kāi) gank.io,搜索"雪花":

看樣子第7個(gè)庫(kù)就是我們想要的了,點(diǎn)進(jìn)源碼,直接 download 不解釋?zhuān)浀?star 一個(gè)支持作者。那么現(xiàn)在我們的項(xiàng)目中就有一個(gè)完整的下雪效果 View 了。

二、實(shí)現(xiàn)雪人播放器 View

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

接下來(lái)要找一個(gè)小雪人的圖片當(dāng)作播放器的背景,那么阿姆斯特朗...不對(duì),是這個(gè):

嗯,相當(dāng)可愛(ài)喜慶。那么播放器核心代碼如下:

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(), "開(kāi)始播放", Toast.LENGTH_SHORT).show();
  setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    if (!mediaPlayer.isPlaying()) {
     mediaPlayer.start();
     Toast.makeText(getContext(), "繼續(xù)播放", 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之后自動(dòng)播放
   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();
  }
 }
}

三、動(dòng)態(tài)加載思路

上面基本實(shí)現(xiàn)了在本地的雪花以及播放音樂(lè)效果,那么在不更新主程序的情況下,如何將這兩個(gè)View動(dòng)態(tài)加載到主程序當(dāng)中去呢?

首先我們明白,Android 的DexClassloader 是擁有加載任意APK 中任意類(lèi)的能力的,只是有以下限制:

加載出的Activity 由于不在宿主 Manifest 文件中聲明,因此框架無(wú)法找到并初始化這個(gè)Activity。

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

加載出的類(lèi)的Resource 文件id 會(huì)和主程序混淆在一起。

由于我們只是加載View,并不是加載整個(gè)Activity,所以前兩個(gè)問(wèn)題并不會(huì)遇到,而第三個(gè)問(wèn)題可以想辦法解決掉。

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

把能夠裝載View的ViewGroup 的空位留出來(lái)

去獲取更新的patch包

把View 從apk包中加載出來(lái)之后,放進(jìn)留好的ViewGroup 中。

這樣一來(lái),不僅是圣誕節(jié),在之后的各種活動(dòng)上都可以在線(xiàn)去加載活動(dòng)的View。

四、開(kāi)始加載

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

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原來(lái)的資源管理器,也就是說(shuō)現(xiàn)在可以在宿主中訪(fǎng)問(wèn)插件資源了。

核心加載代碼如下:

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 View
if (dynamicView == null) {
 dynamicView = (View) con.newInstance(getContext());
}
//Replace the View's mResources and recovery the Activity's avoid disorder of Resources
Reflect.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);

中間對(duì) mResources 的操作的作用是:將宿主的Activity 的mResources 重置,避免在Activity 中使用資源時(shí)和插件沖突。

然而機(jī)智的我已經(jīng)把更新包下載、版本管理、動(dòng)態(tài)加載都封裝好了,所以正確的加載方式是:

引用它: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="原始頁(yè)面"
   />
 </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>

以上聲明了主界面的布局,當(dāng)然,在動(dòng)態(tài)加載之前除了原有的"原始頁(yè)面"TextView,是不會(huì)有任何其他東西的,也就是圣誕節(jié)來(lái)臨之前的程序。注意:uuid 會(huì)和在線(xiàn)包相匹配。

2.打插件包

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

3.把插件包放到服務(wù)器

在服務(wù)器返回的JSON中聲明插件包地址和動(dòng)態(tài)View 的一些參數(shù),這里的演示程序請(qǐng)求地址為:

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
  }
 }
 ]
}

我們聲明了這次在線(xiàn)包的版本,每個(gè)View 的包名和布局參數(shù), 以及最重要的 和宿主程序中聲明對(duì)齊的uuid。

以上所述是小編給大家介紹的Android中利用動(dòng)態(tài)加載實(shí)現(xiàn)手機(jī)淘寶的節(jié)日特效,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

最新評(píng)論