动态壁纸android_android9.0 动态壁纸和静态壁纸 - CSDN
精华内容
参与话题
  • 这两天在公众号上偶然看到一篇关于设置动态壁纸的文章,觉得蛮有意思的,学习了一下,以此文章记录一下怎样给手机设置静态壁纸和动态壁纸,设置壁纸的使用方法。 静态壁纸 设置静态壁纸是通过调用系统...

    这两天在公众号上偶然看到一篇关于设置动态壁纸的文章,觉得蛮有意思的,学习了一下,以此文章记录一下怎样给手机设置静态壁纸和动态壁纸,设置壁纸的使用方法。

    静态壁纸

    Android中WallpaperManager系统服务用于管理壁纸的运行与切换,并通过WallpaperManager类向外界提供操作壁纸的接口。
    设置静态壁纸是通过调用系统WallpaperManager的方法来实现的,
    主要分为下面三种,同一种因不同的方法参数会对应多个方法:
    (1)通过bitmap设置壁纸:setBitmap
    (2)通过资源文件设置壁纸:setResource
    (3)通过流设置壁纸:setStream
    具体例子如下:

    WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
        try {
          Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
          wallpaperManager.setBitmap(bitmap);
        } catch (IOException e) {
          e.printStackTrace();
        }
    

    注意
    (1)设置壁纸需要声明权限

    <uses-permission android:name="android.permission.SET_WALLPAPER" />
    

    (2)壁纸分系统壁纸和锁屏壁纸,但是API 24才能调用系统api设置。
    比如:

    WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
        try {
          if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            wallpaperManager.setResource(R.raw.wallpaper, WallpaperManager.FLAG_SYSTEM);
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
    

    其中WallpaperManager.FLAG_SYSTEM表示系统壁纸,WallpaperManager.FLAG_LOCK表示锁屏壁纸。
    既然可以设置壁纸,相对应的就可以清除壁纸,具体如下:

    WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
        try {
          wallpaperManager.clear();
        } catch (IOException e) {
          e.printStackTrace();
        }
    

    动态壁纸

    动态壁纸是通过Android中的WallpaperService服务启动并开始进行壁纸的绘制工作,其中内部类Engine,实现了壁纸窗口的创建以及Surface的维护工作。
    那怎样实现一个简单的动态壁纸呢?主要分为以下几步:
    1.定义MyWallpaperService继承WallpaperService并实现onCreateEngine方法,返回自己的Engine实现类:

    public class MyWallpaperService extends WallpaperService {
      //  实现动态壁纸必须要实现的抽象方法
      @Override
      public Engine onCreateEngine() {
        bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.star);
        return new MyEngine();
      }
    }
    

    其中在MyEngine中通过对生命周期方法的调用实现壁纸进行动画和绘制工作:

    class MyEngine extends Engine{
        @Override
        public void onCreate(SurfaceHolder surfaceHolder) {
          super.onCreate(surfaceHolder);
          当引擎初始化时被调用,此时绘制surface还未被创建
          可以进行paint等的初始化工作
        }
    
        @Override
        public void onVisibilityChanged(boolean visible) {
          super.onVisibilityChanged(visible);
         当壁纸可见或隐藏时被调用,应该暂停你的动画,不再绘制任何东西,以节省CPU(比如说移除Runnable等)。
        }
        @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
          super.onSurfaceCreated(holder);
          当surface被创建时被调用
        }
    
        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
          super.onSurfaceChanged(holder, format, width, height);
          当surface的图形结构发生变化(大小、格式)
        }
    
        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
          super.onSurfaceDestroyed(holder);
          当surface被销毁时被调用
        }
    
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep,
            int xPixelOffset, int yPixelOffset) {
          super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset,
              yPixelOffset);
              当壁纸发生偏移变化,例如用户左右滑动主屏幕,这个可以用来创建一个平行滑动的效果,就是用户滑动时,壁纸同时发生偏移。
        }
    
        @Override
        public void onTouchEvent(MotionEvent event) {
          super.onTouchEvent(event);
          当显示壁纸时,用户跟主屏幕有触摸交互时被调用
        }
    
        @Override
        public void onDestroy() {
          super.onDestroy();
          引擎销毁时被调用。此方法调用之后,引擎变得不可用。
        }
      }
    

    2.配置AndroidManifest.xml,声明上述中的自定义的service和一个SettingActivity:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.example.liuwei.wallpagerdemo">
    
      <uses-permission android:name="android.permission.SET_WALLPAPER" />
      <uses-feature
        android:name="android.software.live_wallpaper"
        android:required="true"/>
    
      <application
       ......
        <activity android:name=".SettingActivity"
          android:exported="true"
          android:label="@string/app_name"/>
      
        <service android:name=".MyWallpaperService"
          android:enabled="true"
          android:label="@string/app_name"
          android:permission="android.permission.BIND_WALLPAPER">
    
          <intent-filter android:priority="1">
            <action android:name="android.service.wallpaper.WallpaperService"/>
          </intent-filter>
    
          <meta-data
            android:name="android.service.wallpaper"
            android:resource="@xml/wallpager"/>
        </service>
      </application>
    
    </manifest>
    

    注意:
    (1)设置动态壁纸需要在MyWallpaperService中声明android:permission="android.permission.BIND_WALLPAPER权限
    (2)必须声明,表示动态壁纸

    <uses-feature
        android:name="android.software.live_wallpaper"
        android:required="true"/>
    

    (3)声明MyWallpaperService的action为android:name="android.service.wallpaper.WallpaperService,其中在meta-data中有一个resource在下一步中说明。
    可能比较疑惑为什么要创建SettingActivity,关于为什么创建SettingActivity,在下述中说明。
    3.在res/xml下创建xml文件,我这里命名为wallpaper.xml,为上述中service中的resource:

    <?xml version="1.0" encoding="utf-8"?>
    <wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
      android:description="@string/app_name"
      android:settingsActivity="com.example.liuwei.wallpagerdemo.SettingActivity"
      android:thumbnail="@mipmap/star" />
    

    其中description(应用描述)settingsActivity(应用指定的壁纸设置页面),thumbnail(应用图标)三个属性自定义设置。
    4.配置工作完成,启动壁纸服务:
    通过下面这种方式打开壁纸设置页面设置动态壁纸:

    Intent intent = new Intent(
            WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
        intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
            new ComponentName(this, MyWallpaperService.class));
        startActivity(intent);
    

    这时候心里想MyWallpaperService是service,那能不能通过startService()启动壁纸,通过stopService()清除壁纸呢?
    经测试,不能。这也是上述声明SettingActivity的原因。
    **所以启动壁纸服务时,不能通过context的startService()方法来启动壁纸服务,需要通过启动系统的预览界面来间接启动服务。**但明明是一个service为什么这种方式不能成功设置壁纸呢,在下述原理中说明。
    通过以上四个步骤我们就可以设置动态壁纸了,在运行app时点击设置动态壁纸进入到下面页面:
    在这里插入图片描述
    点击应用就可以应用此动态壁纸,但是点击设置按钮,因为这个例子中的的SettingActivity继承的是PreferenceActivity,进入到下面页面:
    在这里插入图片描述
    此页面内容为SettingActivity中设置的PreferenceScreen的xml文件,可以通过设置xml文件在此页面中对动态壁纸进行设置:

    public class SettingActivity extends PreferenceActivity {
    
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.prefs);
        Preference circlePreferennce = getPreferenceScreen().findPreference("numberOfCircles");
        circlePreferennce.setOnPreferenceChangeListener(numberCheckListener);
      }
    
      Preference.OnPreferenceChangeListener numberCheckListener = new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
          if(newValue != null && newValue.toString().length() > 0 && newValue.toString().matches("\\d*")){
            return true;
          }
          return false;
        }
      };
    }
    

    res/xml下的prefs.xml文件:

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    
      <CheckBoxPreference
        android:key="touch"
        android:title="Touch"/>
    
      <EditTextPreference
        android:key="numberOfCircles"
        android:title="Number"/>
    </PreferenceScreen>
    

    使用PreferenceActivity还可以做一些其他事情,关于PreferenceActivity的用法请参考这里
    最后关于清除动态壁纸
    可以使用上述中的清除静态壁纸的方法进行清除,或是如下利用WallpaperService的onDestroy方法:

    if(myWallpaperService != null){
          myWallpaperService.onDestroy();
        }
    

    除此之外,还可以使用视频,gif等设置动态壁纸,流程相同,只是在Engine中的不同的实现对壁纸进行不同的绘制工作,后续有时间学习一下,再补充。
    学习demo点击这里

    原理

    知道了怎样设置静态壁纸和动态壁纸之后引发一些思考:动态壁纸需要自定义继承WallpaperService,在onCreateEngine中返回Engine实现,为什么静态壁纸只需要调用WallpaperManager的api方法就可以呢?而动态壁纸继承WallpaperService也就说明了是一个service,为什么通过startService启动方式不能成功设置动态壁纸呢?系统是怎样通过WallpaperService进行通信的?此时需要了解动态壁纸和静态壁纸的原理了。
    对于上述几个疑问:
    1.通信:
    动态壁纸和静态壁纸都是以一个Service的形式运行在系统后台,并在一个类型为TYPE_WALLPAPER的窗口上绘制内容。
    WallpaperService是由WallpaperManagerService(系统Service,在系统启动时,由系统进程SystemServer创建)启动(通过绑定服务的方式)并管理的。
    在设置壁纸时,应用程序通过WallpaperManager通过AIDl与WallpaperManagerService进行通信。
    Android的动态墙纸虽然似乎是显示在Launcher的背景里,但其实这只是假象,动态墙纸和Launcher是完全不同的两个进程,只不过Launcher和动态墙纸的进程可以通过框架里的WallpaperManager进行进程间通信罢了,用户在Launcher桌面滑动、点击屏幕时有的动态墙纸能产生交互效果,实际上就是这个进程通信完成的。如果你通过代码将Launcher的背景设置为非透明的,比如以不透明的图片或者颜色作为背景,那么,你将看不到任何动态墙纸效果,当然,这样的话,静态墙纸你也不会看到了。
    2.启动动态壁纸方法:
    查看源码可知,启动动态壁纸是通过WallpaperManager.java的setWallpaperComponent这个方法实现的,如下:

    @SystemApi
        @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
        public boolean setWallpaperComponent(ComponentName name) {
            return setWallpaperComponent(name, mContext.getUserId());
        }
    

    setWallpaperComponent这个方法是系统api,不能直接被开发者调用,因此第三方应用程序是无法进行动态壁纸的设置的,只能通过上述中的方法启动动态壁纸。
    3.静态壁纸:
    ImageWallpaper表示静态壁纸,对应静态壁纸,系统中有一个ImageWallpaper(继承自WallpaperService) 和DrawableEngine(继承自Engine)。
    查看源码深入理解壁纸原理请点击这里

    参考

    https://mp.weixin.qq.com/s/4_ER7XsObMjRfHGOkOWmhg
    https://blog.csdn.net/wangjinyu501/article/details/83317542
    https://blog.csdn.net/qxs965266509/article/details/61925652
    https://blog.csdn.net/u012968084/article/details/52160399
    https://blog.csdn.net/leopard21/article/details/32201501

    展开全文
  • Android自定义动态壁纸开发

    千次阅读 多人点赞 2019-01-06 18:35:47
    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现。 一、动态壁纸原理 如果你了解使用过SurfaceView的话,那么开发一款动态壁纸对你来说其实非常简单。 动态壁纸的本质其实...

    看到有些手机酷炫的动态壁纸,有没有好奇过他们是如何实现的,其实我们自己也可以实现。

    一、动态壁纸原理

    如果你了解使用过SurfaceView的话,那么开发一款动态壁纸对你来说其实非常简单。

    动态壁纸的本质其实就是一个服务在维护一个动态壁纸引擎Engine,所以我们看到的动态效果其实是通过这个引擎画出来的。而维护这个引擎的服务,就是WallpaperService。本篇文章并不讨论内部实现原理,只是让大家知道如何去实现动态壁纸,所以就不详细说了。

     

    二、实现动态壁纸

    大体上可分为三个步骤:

    1. 创建自定义WallpaperService继承WallpaperService
    2. 在Manifest中注册该Service并添加相关属性
    3. 创建所需要的xml文件

    1.创建自定义WallpaperService

    public class MyLwp extends WallpaperService {
        @Override
        public Engine onCreateEngine() {
            return new MyEngine();
        }
    
        class MyEngine extends  Engine{
            @Override
            public SurfaceHolder getSurfaceHolder() {
                return super.getSurfaceHolder();
            }
    
            @Override
            public void onCreate(SurfaceHolder surfaceHolder) {
                super.onCreate(surfaceHolder);
            }
    
            @Override
            public void onDestroy() {
                super.onDestroy();
            }
    
            @Override
            public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                super.onSurfaceChanged(holder, format, width, height);
            }
    
            @Override
            public void onSurfaceCreated(SurfaceHolder holder) {
                super.onSurfaceCreated(holder);
            }
    
            @Override
            public void onSurfaceDestroyed(SurfaceHolder holder) {
                super.onSurfaceDestroyed(holder);
            }
        }
    }

    2.Manifest注册

            <service
                android:name=".MyLwp"
                android:enabled="true"
    
                android:permission="android.permission.BIND_WALLPAPER">
                <intent-filter>
                    <action android:name="android.service.wallpaper.WallpaperService" />
                </intent-filter>
                <meta-data
                    android:name="android.service.wallpaper"
                    android:resource="@xml/livewallpapervideo" />
            </service>

    一定要添加的几个地方:permission、intent-filter、meta-data。

    3.创建需要的xml文件

    这个xml文件就是Manifest中meta-data中的resource需要的文件:

    <?xml version="1.0" encoding="utf-8"?>
    <wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
        android:description="@string/app_name"
        android:settingsActivity="ASD"
        android:thumbnail="@mipmap/ic_launcher"/>

    需要注意第二个属性:settingsActivity,这个属性可以设置也可以不设置,他是启动一个设置动态壁纸的界面,一般情况下其实用不到这个界面,我们一般会使用PreferenceActivity去实现。下面是添加该属性和不添加该属性的区别:

    完成这些之后,就是我们设计动态壁纸的时候了。回到自定义的Wallpaper类中:

    我们当时在类中自定义了一个内部类MyEngine继承自Engine。这个Engine就是用来绘制的。关于Engine的几个主要方法如下:

        class MyEngine extends  Engine{
            //获取SurfaceHolder时调用
            @Override
            public SurfaceHolder getSurfaceHolder() {
                return super.getSurfaceHolder();
            }
    
            //手势移动时回调
            @Override
            public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
                super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
            }
    
            //Surface创建时回调
            @Override
            public void onSurfaceCreated(SurfaceHolder holder) {
                super.onSurfaceCreated(holder);
            }
    
            //Surface销毁时回调
            @Override
            public void onSurfaceDestroyed(SurfaceHolder holder) {
                super.onSurfaceDestroyed(holder);
            }
        }

    onOffsetsChanged要注意一下,还记得有的手机滑动桌面时候背景图片会跟着左右移动吗,这个方法就可以实现这个效果,在手势滑动的每一帧都会回调依次。一下是个人理解的参数的含义:

    xOffset:x方向滑动的百分比(与桌面分页数有关)

    yOffset:y方向滑动百分比(一般用不到)

    xOffsetStep:x方向每个分页所占的百分比(1 / xOffsetStep = 桌面的分页数)

    yOffsetStep:同

    xPixelOffset:x放下像素偏移量

    y。。。。。

     

    4.绘制。

    实现绘制的方式,就跟SurfaceView的绘制一样了:

            @Override
            public void onSurfaceCreated(SurfaceHolder holder) {
                super.onSurfaceCreated(holder);
                Canvas canvas = holder.lockCanvas();
                canvas.drawColor(Color.RED);
                holder.unlockCanvasAndPost(canvas);
            }

    我只是简单的话了一个红色背景,效果如下:

    当然可以实现很多不同的效果,这个就根据不同的需求去实现了。

    展开全文
  • Android OpenGL动态壁纸

    千次阅读 2017-08-14 15:38:03
    Android OpenGL动态壁纸 1、动态壁纸的Service组件 WallpaperService提供了基本的动态壁纸的实现。 public class GLWallpaperService extends WallpaperService { @Override public Engine onCreateEngine() { ...

    Android OpenGL动态壁纸

    首先申明下,本文为笔者学习《OpenGL ES应用开发实践指南》的笔记,并加入笔者自己的理解和归纳总结。

    1、动态壁纸的Service组件

    WallpaperService提供了基本的动态壁纸的实现。
    public class GLWallpaperService extends WallpaperService {
    
        @Override
        public Engine onCreateEngine() {
            return new GLEngine();
        }
    
    }

    2、创建自定义GLSurfaceView

    GLSurfaceView会调用getHolder()来添加界面,只需重载getHolder方法,返回动态壁纸的渲染表面。onWallpaperDestroy在销毁动态壁纸时被调用,使用GLSurfaceView的onDetachedFromWindow方法。
    class WallpaperGLSurfaceView extends GLSurfaceView {
    
    	public WallpaperGLSurfaceView(Context context) {
    		super(context);
    	}
    
    	@Override
    	public SurfaceHolder getHolder() {
    		return GLEngine.this.getSurfaceHolder();
    	}
    
    	public void onWallpaperDestroy() {
    		super.onDetachedFromWindow();
    	}
    }

    3、Engine类

    GLEngine继承Engine类,当动态壁纸创建时,调用GLEngine的onCreate方法来初始化,销毁时调用onDestroy方法。当动态壁纸可见或者隐藏时,onVisibilityChanged方法会被调用。
    public class GLEngine extends Engine {
    	@Override
    	public void onCreate(SurfaceHolder surfaceHolder) {
    		super.onCreate(surfaceHolder);
    	}
    
    	@Override
    	public void onVisibilityChanged(boolean visible) {
    		super.onVisibilityChanged(visible);
    	}
    
    	@Override
    	public void onDestroy() {
    		super.onDestroy();
    	}
    
    }
    完善动态壁纸的生命周期,在onCreate中创建GLSurfaceView,onDestroy中销毁。
    private WallpaperGLSurfaceView mSurfaceView;
    		
    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
    	super.onCreate(surfaceHolder);
    
    	mSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this);
    }
    	
    public void onVisibilityChanged(boolean visible) {
    	super.onVisibilityChanged(visible);
    
    	if (mRender) {
    		if (visible) {
    			mSurfaceView.onResume();
    		} else {
    			mSurfaceView.onPause();
    		}
    	}
    }
    
    @Override
    public void onDestroy() {
    	super.onDestroy();
    
    	mSurfaceView.onWallpaperDestroy();
    }

    4、添加配置

    在AndroidManifest.xml中添加
    <uses-feature android:name="android.software.live_wallpaper" />
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
    表明这个应用包含一个动态壁纸,并且还需要OpenGL ES 2.0或以上版本。
    还需要添加动态壁纸Service的引用
    <service android:name=".opengl.GLWallpaperService"
    	android:label="@string/app_name"
    	android:permission="android.permission.BIND_WALLPAPER" >
    	<intent-filter>
    		<action android:name="android.service.wallpaper.WallpaperService" />
    	</intent-filter>
    	<meta-data
    		android:name="android.service.wallpaper"
    		android:resource="@xml/wallpaper" />
    </service>
    在资源目录res/xml下,添加wapaper.xml文件
    <?xml version="1.0" encoding="utf-8"?>
    <wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
        android:thumbnail="@drawable/ic_wallpaper" />

    5、体验动态壁纸

    (1) 切换到设备的主屏幕上,按住屏幕的空白部分,直至弹出一个菜单。
    (2) 选择"动态壁纸",从弹出的列表中选择我们自己的动态壁纸。
    (3) 选择"设置壁纸"


    6、随主屏幕滚动背景

    当你在主屏幕上的不同页面之间来回滑动时,动态壁纸没有移动,通过Engine的onOffsetsChanged方法,可以是实现动态壁纸的滚动效果。
    public void onOffsetsChanged(final float xOffset, final float yOffset, float xOffsetStep,
    							 float yOffsetStep, int xPixelOffset, int yPixelOffset) {
    	mSurfaceView.queueEvent(new Runnable() {
    		@Override
    		public void run() {
    			mShaderRender.handleOffsetsChanged(xOffset, yOffset);
    		}
    	});
    }

    7、GLWallpaperService类

    public class GLWallpaperService extends WallpaperService {
    
        @Override
        public Engine onCreateEngine() {
            return new GLEngine();
        }
    
        public class GLEngine extends Engine {
            private WallpaperGLSurfaceView mSurfaceView;
            private OpenGLParticleShaderRender mShaderRender;
            private boolean mRender;
    
            @Override
            public void onCreate(SurfaceHolder surfaceHolder) {
                super.onCreate(surfaceHolder);
    
                mSurfaceView = new WallpaperGLSurfaceView(GLWallpaperService.this);
    
                ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
                ConfigurationInfo configurationInfo = am.getDeviceConfigurationInfo();
    
                boolean supportEs2 = configurationInfo.reqGlEsVersion >= 0x20000;
    
                if (supportEs2) {
                    // 选择OpenGL ES 2.0
                    mSurfaceView.setEGLContextClientVersion(2);
                    mShaderRender = new OpenGLParticleShaderRender();
                    // 设置渲染
                    mSurfaceView.setRenderer(mShaderRender);
                    mRender = true;
                } else {
                    Toast.makeText(GLWallpaperService.this ,
                            "This device does not support OpenGL ES 2.0",
                            Toast.LENGTH_LONG).show();
                }
            }
    
            @Override
            public void onVisibilityChanged(boolean visible) {
                super.onVisibilityChanged(visible);
    
                if (mRender) {
                    if (visible) {
                        mSurfaceView.onResume();
                    } else {
                        mSurfaceView.onPause();
                    }
                }
            }
    
            @Override
            public void onDestroy() {
                super.onDestroy();
    
                mSurfaceView.onWallpaperDestroy();
            }
    
            @Override
            public void onOffsetsChanged(final float xOffset, final float yOffset, float xOffsetStep,
                                         float yOffsetStep, int xPixelOffset, int yPixelOffset) {
                mSurfaceView.queueEvent(new Runnable() {
                    @Override
                    public void run() {
                        LogUtil.log("GLEngine", "xOffset = " + xOffset + ", yOffset = " + yOffset);
                        mShaderRender.handleOffsetsChanged(xOffset, yOffset);
                    }
                });
            }
    
            class WallpaperGLSurfaceView extends GLSurfaceView {
    
                public WallpaperGLSurfaceView(Context context) {
                    super(context);
                }
    
                @Override
                public SurfaceHolder getHolder() {
                    return GLEngine.this.getSurfaceHolder();
                }
    
                public void onWallpaperDestroy() {
                    super.onDetachedFromWindow();
                }
            }
    
        }
    
        private class OpenGLParticleShaderRender implements GLSurfaceView.Renderer {
            private Particle mParticle;
            private ParticleProgram mParticleProgram;
            private ParticleShooter mRedParticleShooter, mGreenParticleShooter, mBlueParticleShooter;
            private long mGlobalStartTime;
    
            private float[] projectionMatrix = new float[16];
            private float[] viewMatrix = new float[16];
            private float[] viewProjectionMatrix = new float[16];
    
            private float xOffset, yOffset;
    
            @Override
            public void onSurfaceCreated(GL10 gl, EGLConfig config) {
                GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.1f);
    
                GLES20.glEnable(GLES20.GL_BLEND);
                GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
    
                mParticleProgram = new ParticleProgram(GLWallpaperService.this);
                mParticle = new Particle(10000);
    
                mGlobalStartTime = System.nanoTime();
    
                final Geometry.Vector particleDirection = new Geometry.Vector(0f, 0.5f, 0f);
    
                mRedParticleShooter = new ParticleShooter(new Geometry.Point(-1, 0, 0),
                        particleDirection, Color.rgb(250, 50, 5));
    
                mGreenParticleShooter = new ParticleShooter(new Geometry.Point(0, 0, 0),
                        particleDirection, Color.rgb(25, 255, 25));
    
                mBlueParticleShooter = new ParticleShooter(new Geometry.Point(1, 0, 0),
                        particleDirection, Color.rgb(5, 50, 255));
                final float angleVarianceInDegrees = 5f;
                final float speedVariance = 1f;
    
                mRedParticleShooter = new ParticleShooter(new Geometry.Point(-1, 0, 0),
                        particleDirection, Color.rgb(250, 50, 5), angleVarianceInDegrees, speedVariance);
    
                mGreenParticleShooter = new ParticleShooter(new Geometry.Point(0, 0, 0),
                        particleDirection, Color.rgb(25, 255, 25), angleVarianceInDegrees, speedVariance);
    
                mBlueParticleShooter = new ParticleShooter(new Geometry.Point(1, 0, 0),
                        particleDirection, Color.rgb(5, 50, 255), angleVarianceInDegrees, speedVariance);
            }
    
            @Override
            public void onSurfaceChanged(GL10 gl, int width, int height) {
                // 设置视图尺寸
                GLES20.glViewport(0, 0, width, height);
    
                // 创建透视投影
                Matrix.perspectiveM(projectionMatrix, 0, 45, (float)width / (float)height, 1f, 10f);
    
                updateViewMatrices();
            }
    
            @Override
            public void onDrawFrame(GL10 gl) {
                // 清空屏幕
                GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT);
    
                float currentTime = (System.nanoTime() - mGlobalStartTime) / 1000000000f;
                mRedParticleShooter.addParticles(mParticle, currentTime, 5);
                mGreenParticleShooter.addParticles(mParticle, currentTime, 5);
                mBlueParticleShooter.addParticles(mParticle, currentTime, 5);
    
                mParticleProgram.setUniform(viewProjectionMatrix);
                mParticleProgram.setCurrentTime(currentTime);
                mParticle.bindData(mParticleProgram);
                mParticle.draw();
            }
    
            private void handleOffsetsChanged(float xOffset, float yOffset) {
                this.xOffset = (xOffset - 0.5f) * 2.5f;
                this.yOffset = (yOffset - 0.5f) * 2.5f;
                updateViewMatrices();
            }
    
            private void updateViewMatrices() {
                // 定义模型矩阵
                Matrix.setIdentityM(viewMatrix, 0);
                Matrix.translateM(viewMatrix, 0, 0f - xOffset, -1.5f - yOffset, -5f);
    
                Matrix.multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
            }
    
        }
    
    }
    显示如下


    展开全文
  • 打开动态壁纸时一直显示动态壁纸正在加载 报错信息: 无!(这是最难受的 /(ㄒoㄒ)/~~ )。 问题原因: 粗心导致!把本应返回的MyEngine类写成了Engine。 问题代码块: public class MyGLWallpaperService extends ...
    1. 打开动态壁纸时一直显示动态壁纸正在加载

    报错信息: 无!(这是最难受的 /(ㄒoㄒ)/~~ )。
    问题原因: 粗心导致!把本应返回的MyEngine对象写成了Engine
    问题代码块:

    public class MyGLWallpaperService extends WallpaperService {
     
        @Override
        public Engine onCreateEngine() {
            return new Engine();//<---------------就是这里
        }
        class MyEngine extends Engine{
        //......
        }
    }
    

    问题代码: return new Engine();
    解决办法:onCreateEngine()方法中返回的Engine改成MyEngine

    总结:本来百思不得其解,百度亦不得其解,但在不经意间掠过了代码的某一处就发现问题所在,真是造化弄人啊!所以同志们,在遇到这种bug时先不要worry,可能只是缘分未到,一定要按时睡觉!!!

    1. 打开动态壁纸时程序直接崩溃,显示xxxActivity已停止运行
      报错信息: A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 2128 (GLThread 115)
      问题原因: GLThread报错,具体未知(如果有知道的,欢迎评论指教)。
      问题代码块:
       class MyEngine extends Engine{
       GLSurfaceView glView = null;
       MyRender render = null;
       //......
    	   private void onCreate(SurfaceHolder holder){
    	   		super.onCreate(holder);
    	   		glView = new GLSurfaceView(MyGLWallpaperService.this);
    	   		final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
                final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
                final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000
                        ||(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
                        &&(Build.FINGERPRINT.startsWith("generic"))
                        || Build.FINGERPRINT.startsWith("unknow")
                        || Build.MODEL.contains("google_sdk")
                        || Build.MODEL.contains("Emulator")
                        || Build.MODEL.contains("Android SDK built for x86");
    	   		//通知默认的EGLContextFactory和默认的EGLConfigChooser选择哪个EGLContext客户端版本。
    			if(supportsEs2){
    				glView.setEGLContextClientVersion(2);//<-------------------问题在这里
    				render = new MyRender(MyGLWallpaperService.this);
    				glView.setRenderer(render);
    			}else{
    				Toast.makeText(MyGLWallpaperService.this ,
                            "This device does not support OpenGL ES 2.0",
                            Toast.LENGTH_LONG).show();
    			}
    			
    	   	
    	   }
       //......
       }
    

    问题代码: glView.setEGLContextClientVersion(2);
    解决办法:glView.setEGLContextClientVersion(2);删掉。

    总结:适合别人的代码不一定适合自己!

    展开全文
  • android动态壁纸开发(能运行的)

    千次阅读 2016-09-13 20:03:01
    网上也有讲开发动态壁纸的博客,我在看书编写这个例子时,发现我编写的动态壁纸找不到,后来发现是没有将我编写的WallpaperService跑起来,而书上和有点博客照搬写到是不需要Activity的,我发现没有Activity的话,...
  • Android 动态壁纸 Livepaper

    千次阅读 2013-03-05 11:06:48
     最近做动态壁纸的项目,原来觉得动态壁纸是个很小的项目,但是看到Android Market上有个专门的动态壁纸分类(现在升级为Google Play了), 而且自己做的这个项目可连接上服务器,供用户购买下载图片,终于有了自信,...
  • 找了半天两个问题的root cause都是手机动态壁纸。我们手机动态壁纸的实现是无论当前壁纸是否处于前台,video instance都是一直活跃的。不得不说,这个设计真的很过分,一是浪费资源,二是会引起很多video的问题。...
  • Android 动态壁纸开发(时钟)

    千次阅读 2017-04-19 16:44:04
    Android 动态壁纸开发(时钟)这是我人生第一篇文章,希望大家不喜无喷啊!有兴趣的可以看看玩,因为语言组织能力有限,就废话不多说直接进入重点! 先看效果 上图是动态壁纸钟的一个时钟。 我们先来看看 Live...
  • 动态壁纸是在Android 2.1新增的一个功能。动态壁纸可以添加到Android的桌面,具有交互式的动画背景效果。在本教程中,我们将教会你如何去制作一个交互式的动态壁纸动态壁纸是一个Android应用程序,包括一个服务...
  • 本站之前介绍过一个樱花动态壁纸和一个气泡动态壁纸,点击分类里面的壁纸分类就可以看到,但是如果您想学习一下安卓动态壁纸的开发一定不能错过这个项目。本项目完全可以作为动态壁纸开发的指导案例,整个项目只有三...
  • Android4.4原生动态壁纸源码: Basic、Galaxy4、HoloSpiral、LivePicker、MagicSmoke、MusicVisualization、NoiseField、PhaseBeam
  • -- 动态壁纸 Android中模仿探究抖音短视频的动态壁纸功能以及动态壁纸的拓展功能使用- https://blog.csdn.net/jiangwei0910410003/article/details/80461169 DragVideo,一种在播放视频时,可以任意拖拽的方案- ...
  • 代码效果图:由于是在虚拟机... 跟大家分享一下 大家觉得能够的话就帮助下下~{:soso_e113:}游戏源码项目下载:http://code.662p.com/view/2312.html详细说明:http://android.662p.com/thread-295-1-1.html 转载...
  • Android动态桌面,设置壁纸

    千次阅读 2018-11-06 21:11:00
    最近要做一个动态桌面。...1.2这个WallpaperManager里面有多种方式设置静态壁纸,需要android.Manifest.permission.SET_WALLPAPER这个权限不要忘记设置 1.2.1通过资源文件 这个是第二个方法,比第一个多...
  • 效果图,图中桌面背景为一段...对动态壁纸进行一些设置 在res下创建一个xml文件夹,在创建一个wallpager标签文件 <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@mi
  • android中我们一般设置静态壁纸,使用WallpaperManager可以轻松达到目的,但是使用WallpaperManager是不能够设置动态壁纸的,为此android提供了一个WallpaperService专门用来设置动态壁纸,那么我们就用几个简单的...
  • android 7.1 默认动态壁纸

    千次阅读 2018-01-22 19:36:13
    最近客户提了个需求:升级后默认使用动态壁纸。 但是根据网络资料大量修改动态壁纸的都是修改frameworks/base/core/res/res/values/config.xml文件中 default_wallpaper_component就好了。 我尝试改了一下,升级...
  • 本文实例讲述了Android编程之动态壁纸。分享给大家供大家参考,具体如下: 从android 2.1版本起引入了动态壁纸的概念,熟悉android的人一定不会陌生。这里解释一个动态壁纸是怎么形成又是怎么工作的。 首先...
  • Android 应用背景加载系统动态壁纸

    千次阅读 2017-07-11 18:49:24
    Android 应用背景加载系统动态壁纸需求客户的需求总是那么让人摸不着头脑,我们的应用和系统的launcher是共同存在的双桌面形式,客户要求应用必须支持系统桌面的壁纸,针对这个需求,静态壁纸很容易实现,但是动态...
1 2 3 4 5 ... 20
收藏数 4,320
精华内容 1,728
关键字:

动态壁纸android