Android中利用动态加载实现手机淘宝的节日特效

相信去年圣诞节打开过手机淘宝的童鞋都会对当时的特效记忆犹新吧:全屏飘雪,旁边还有个小雪人来控制八音盒背景音乐的播放,让人有种身临其境的感觉,甚至忍不住想狠狠购物了呢(误),大概就是下面这个样子滴:

嗯,确实很炫,那么我们一步步去分析是如何实现的:

一、实现下雪的 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 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);

中间对 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中利用动态加载实现手机淘宝的节日特效,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

时间: 2024-08-30 05:47:48

Android中利用动态加载实现手机淘宝的节日特效的相关文章

Android中利用动态加载实现手机淘宝的节日特效_Android

相信去年圣诞节打开过手机淘宝的童鞋都会对当时的特效记忆犹新吧:全屏飘雪,旁边还有个小雪人来控制八音盒背景音乐的播放,让人有种身临其境的感觉,甚至忍不住想狠狠购物了呢(误),大概就是下面这个样子滴: 嗯,确实很炫,那么我们一步步去分析是如何实现的: 一.实现下雪的 View 首先,最上面一层的全屏雪花极有可能是一个顶层的View,而这个View是通过动态加载去控制显示的(不更新淘宝也能看到这个效果).那么我们先得实现雪花效果的 View,人生苦短,拿来就用.打开 gank.io,搜索"雪花&quo

Android中的动态加载机制的学习研究_Android

在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病. Android应用开发在一般情况下,常规的开发方式和代码架构就能满足我们的普通需求.但是有些特殊问题,常常引发我们进一步的沉思.我们从沉思中产生顿悟,从而产生新的技术形式. 如何开发一个可以自定

Android中的动态加载机制的学习研究

在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本文对网上Android动态加载jar的资料进行梳理和实践在这里与大家一起分享,试图改善频繁升级这一弊病. Android应用开发在一般情况下,常规的开发方式和代码架构就能满足我们的普通需求.但是有些特殊问题,常常引发我们进一步的沉思.我们从沉思中产生顿悟,从而产生新的技术形式. 如何开发一个可以自定

Android开发中Listview动态加载数据的方法示例

本文实例讲述了Android开发中Listview动态加载数据的方法.分享给大家供大家参考,具体如下: 最近在研究网络数据加载的问题,比如我有几百,甚至上千条数据,这些数据如果一次性全部加载到arraylist,然后再加载到Listview中.我们必然会去单独开线程来做,这样造成的结果就是会出现等待时间很长,用户体验非常不好.我的想法是动态加载数据,第一次加载十条,然后往下面滑动的时候再追加十条,再往下面滑动的时候再去追加,这样大大减少了用户等待的时间,同时给处理数据留下了时间.网上看到了这样一

android中使用jdbc, 加载驱动时总捕获到异常

问题描述 android中使用jdbc, 加载驱动时总捕获到异常 lacat详细信息 jar包我已经add libraries了,问题还是存在 解决方案 最好不要在安卓端用jdbc吧,服务器写php吧,jdbc不推荐的,效率和安全性都不高 解决方案二: 我就问你手机里哪有mysql数据库 解决方案三: e1.printSackTrace(),看这句话的具体错误信息 解决方案四: 你这个出错什么错误了,详细信息打印出来? 你是要连接远程的mysql 吗? 解决方案五: 并没有看到错误是什么,,

解决tableView中cell动态加载控件的重用问题

解决tableView中cell动态加载控件的重用问题 tableView的cell,有时候需要在运行时取得对应的数据后才能够动态的创建该cell中的控件并加载到该cell中,此时,你一定会遇到重用问题,即使你能做到该cell只根据数值加载了一回控件,你也没法保证不出现重用问题:) 效果(请注意查看,移动下面的格子时,上面出现了重用的问题) 源码: YXCell.h // // YXCell.h // YXTableView // // Copyright (c) 2014年 Y.X. All

隐藏-Android中的webview加载完成前后如何用一个图片来进行遮挡加载延迟的闪烁

问题描述 Android中的webview加载完成前后如何用一个图片来进行遮挡加载延迟的闪烁 用webview加载一个链接,但因为网速或者网页内容等问题,出现延迟,但是如果直接打开APP就开始加载的话,如果用户没有网络的情况下打开APP就什么都看不到了.所以想整个LOGO之类的全屏图片,等加载完成了之后再隐藏这个图片.该怎么实现,着急,在线等..... 解决方案 做个全屏的layout,等webview加载完就隐藏掉,在onPageFinished里处理 加载前可以先判断网络是不连通,不通就显示

在android中使用webview加载完一个网页后,如何知道一共加载了多少资源?

问题描述 在android中使用webview加载完一个网页后,如何知道一共加载了多少资源? RT,现在有一个需求要知道用webview加载完任意一个网页后一共有多少个资源,现在问题是不知道什么时候网页完全加载完,因为当webclient回调onPageFinished()之后,还是会继续回调onLoadResource()来加载资源,求给个思路 解决方案 用抓包工具(wireshark)即可查看 解决方案二: 可以在底层抓包实现哦... 解决方案三: 多少资源? 包括多少个图片js 吗 ? 分

有木有大神提供一下android中利用Service后台服务进行手机截屏功能的代码?

问题描述 有木有大神提供一下android中利用Service后台服务进行手机截屏功能的代码? 有木有大神提供一下android中利用Service后台服务进行手机截屏功能的代码,?跪求!是在已经root权限下的