`

Android SetWallpaper

阅读更多
Android setWallpaper涉及到以及几个文件:
Laucher.java
注册Wallpaper change Receiver
Workspace.java
加载壁纸
WallpaperChoose.java
发起Setwallpaper
Context.java
SetWallper的原始接口
ContextWrapper.java
继承Context
ApplicationContext.java
继承Context实现SetWallper
WallpaperService.java
Wallpaper 的一个serivce发出壁纸改变通知Launcher
IWallpaperService.aidl-->WallpaperService.java
IWallpaperServiceCallback.aidle-->ApplicationContext.java



Activity:-- Launcher.WallpaperChoose.java

InputStream stream = getResources().openRawResource(mImages.get(position));
            setWallpaper(stream);

Context.java

public abstract void setWallpaper(InputStream data) throws IOException;

ContextWrapper.java
public class ContextWrapper extends Context

    @Override
    public void setWallpaper(InputStream data) throws IOException {
        mBase.setWallpaper(data);
    }


ApplicationContext.java
class ApplicationContext extends Context
@Override
    public void setWallpaper(InputStream data) throws IOException {
        try {
            ParcelFileDescriptor fd = getWallpaperService().setWallpaper();
            if (fd == null) {
                return;
            }
            FileOutputStream fos = null;
            try {
                fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
                setWallpaper(data, fos);
            } finally {
                if (fos != null) {
                    fos.close();
                }
            }
        } catch (RemoteException e) {
        }
    }

    private void setWallpaper(InputStream data, FileOutputStream fos)
            throws IOException {
        byte[] buffer = new byte[32768];
        int amt;
        while ((amt=data.read(buffer)) > 0) {
            fos.write(buffer, 0, amt);
        }
    }




WallpaperService.java
class WallpaperService extends IWallpaperService.Stub

public ParcelFileDescriptor setWallpaper() {
        checkPermission(android.Manifest.permission.SET_WALLPAPER);
        try {
            ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
                    MODE_CREATE|MODE_READ_WRITE);

            // changing the wallpaper means we'll need to back up the new one
            long origId = Binder.clearCallingIdentity();
            BackupManager bm = new BackupManager(mContext);
            bm.dataChanged();
            Binder.restoreCallingIdentity(origId);

            return fd;
        } catch (FileNotFoundException e) {
            if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
        }
        return null;
    }


    private final FileObserver mWallpaperObserver = new FileObserver(
            WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE) {
                @Override
                public void onEvent(int event, String path) {
                    if (path == null) {
                        return;
                    }

                    File changedFile = new File(WALLPAPER_DIR, path);
                    if (WALLPAPER_FILE.equals(changedFile)) {
                        notifyCallbacks();
                    }
                }
            };




    private void notifyCallbacks() {
        final int n = mCallbacks.beginBroadcast();
        for (int i = 0; i < n; i++) {
            try {
                mCallbacks.getBroadcastItem(i).onWallpaperChanged();
            } catch (RemoteException e) {

                // The RemoteCallbackList will take care of removing
                // the dead object for us.
            }
        }
        mCallbacks.finishBroadcast();
        final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
        mContext.sendBroadcast(intent);

    }



Launcher.java

private static class WallpaperIntentReceiver extends BroadcastReceiver {
        private final Application mApplication;
        private WeakReference<Launcher> mLauncher;

        WallpaperIntentReceiver(Application application, Launcher launcher) {
            mApplication = application;
            setLauncher(launcher);
        }

        void setLauncher(Launcher launcher) {
            mLauncher = new WeakReference<Launcher>(launcher);
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            // Load the wallpaper from the ApplicationContext and store it locally
            // until the Launcher Activity is ready to use it
            final Drawable drawable = mApplication.getWallpaper();
            if (drawable instanceof BitmapDrawable) {
                sWallpaper = ((BitmapDrawable) drawable).getBitmap();
            } else {
                throw new IllegalStateException("The wallpaper must be a BitmapDrawable.");
            }

            // If Launcher is alive, notify we have a new wallpaper
            if (mLauncher != null) {
                final Launcher launcher = mLauncher.get();
                if (launcher != null) {
                    launcher.loadWallpaper();
                }
            }
        }
    }


    private void loadWallpaper() {
        // The first time the application is started, we load the wallpaper from
        // the ApplicationContext
        if (sWallpaper == null) {
            final Drawable drawable = getWallpaper();
            if (drawable instanceof BitmapDrawable) {
                sWallpaper = ((BitmapDrawable) drawable).getBitmap();
            } else {
                throw new IllegalStateException("The wallpaper must be a BitmapDrawable.");
            }
        }
       mWorkspace.loadWallpaper(sWallpaper);
    }



Workspace.java
    void loadWallpaper(Bitmap bitmap) {
        mWallpaper = bitmap;
        mWallpaperLoaded = true;
        requestLayout();
        invalidate();
    }


@Override
    protected void dispatchDraw(Canvas canvas) {
        boolean restore = false;

        // If the all apps drawer is open and the drawing region for the workspace
        // is contained within the drawer's bounds, we skip the drawing. This requires
        // the drawer to be fully opaque.
        if (mLauncher.isDrawerUp()) {
            final Rect clipBounds = mClipBounds;
            canvas.getClipBounds(clipBounds);
            clipBounds.offset(-mScrollX, -mScrollY);
            if (mDrawerBounds.contains(clipBounds)) {
                return;
            }
        } else if (mLauncher.isDrawerMoving()) {
            restore = true;
            canvas.save(Canvas.CLIP_SAVE_FLAG);

            final View view = mLauncher.getDrawerHandle();
            final int top = view.getTop() + view.getHeight();

            canvas.clipRect(mScrollX, top, mScrollX + mDrawerContentWidth,
                    top + mDrawerContentHeight, Region.Op.DIFFERENCE);
        }

        float x = mScrollX * mWallpaperOffset;
        if (x + mWallpaperWidth < mRight - mLeft) {
            x = mRight - mLeft - mWallpaperWidth;
        }

        canvas.drawBitmap(mWallpaper, x, (mBottom - mTop - mWallpaperHeight) / 2, mPaint);

        // ViewGroup.dispatchDraw() supports many features we don't need:
        // clip to padding, layout animation, animation listener, disappearing
        // children, etc. The following implementation attempts to fast-track
        // the drawing dispatch by drawing only what we know needs to be drawn.

        boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
        // If we are not scrolling or flinging, draw only the current screen
        if (fastDraw) {
            drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
        } else {
            final long drawingTime = getDrawingTime();
            // If we are flinging, draw only the current screen and the target screen
            if (mNextScreen >= 0 && mNextScreen < getChildCount() &&
                    Math.abs(mCurrentScreen - mNextScreen) == 1) {
                drawChild(canvas, getChildAt(mCurrentScreen), drawingTime);
                drawChild(canvas, getChildAt(mNextScreen), drawingTime);
            } else {
                // If we are scrolling, draw all of our children
                final int count = getChildCount();
                for (int i = 0; i < count; i++) {
                    drawChild(canvas, getChildAt(i), drawingTime);
                }
            }
        }

        if (restore) {
            canvas.restore();
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        if (widthMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
        }

        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        if (heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Workspace can only be used in EXACTLY mode.");
        }

        // The children are given the same width and height as the workspace
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }

        if (mWallpaperLoaded) {
            mWallpaperLoaded = false;
            mWallpaper = Utilities.centerToFit(mWallpaper, width,
                    MeasureSpec.getSize(heightMeasureSpec), getContext());
            mWallpaperWidth = mWallpaper.getWidth();
            mWallpaperHeight = mWallpaper.getHeight();
        }

        final int wallpaperWidth = mWallpaperWidth;
        mWallpaperOffset = wallpaperWidth > width ? (count * width - wallpaperWidth) /
                ((count - 1) * (float) width) : 1.0f;

        if (mFirstLayout) {
            scrollTo(mCurrentScreen * width, 0);
            mFirstLayout = false;
        }
    }








分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    SetWallPaper

    考虑到Android设备的多样性和版本差异,SetWallPaper可能包含了针对不同API级别的兼容性代码,以确保在多个Android版本上都能正常运行。 10. **版本控制和构建工具** 开发过程中,源码可能使用Git进行版本控制,...

    android 置换手机背景 Gallery与setWallpaper

    "Gallery与setWallpaper"涉及到了从图库应用(Gallery)选择图片并将其设置为壁纸的过程。在这个过程中,开发者通常需要利用Android提供的API来实现这一功能。下面我们将深入探讨这个主题。 首先,Android的Gallery...

    Android-Android设置壁纸兼容国产ROM调用系统自带设置壁纸方法

    在Android开发中,设置壁纸是一项常见的功能,但考虑到国内各种定制化的ROM(如MIUI、EMUI、...此外,SetWallpaper-master 这个项目可能包含了一个示例工程,可以作为参考,研究其源码以了解更多细节和具体实现。

    Android-基于Kotlin开发的一款超简单的图片浏览设置壁纸图片下载的App。

    用户可以选择应用内的图片,并通过调用`setWallpaper(Bitmap)`或`setStream(InputStream)`方法将图片设置为壁纸。为了提供这一功能,开发者可能还会实现一个选择器界面,允许用户选择要设为壁纸的图片。 图片下载...

    Google Android SDK开发范例大全(PDF高清完整版1)(4-1)

    Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1...

    Google Android SDK开发范例大全(PDF完整版4)(4-4)

    Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1...

    Google Android SDK开发范例大全(PDF高清完整版3)(4-3)

    Google Android SDK开发范例大全(完整版)共4个分卷 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 Android初体验 2.1...

    Android动态壁纸

    这个界面通常是一个`Activity`,用户在其中点击按钮触发`WallpaperManager`的`setWallpaper()`或`setLiveWallpaper()`方法,将你的动态壁纸应用到手机上。 8. **性能优化**:由于动态壁纸会在后台持续运行,所以...

    Android与Internet接轨案例源代码

    8.10 远程下载桌面背景图案——URLConnection与setWallpaper()搭配 8.11 将手机文件上传至网站服务器——模拟HTTPFORM的POSTACTION 8.12 移动博客发布器——以XML-RPC达成远程过程调用 8.13 移动RSS阅读器——利用...

    Google Android SDK开发范例大全的目录

    2.2 建立第一个Android项目(HelloAndroid!) 2.3 Android应用程序架构——从此开始 2.4 可视化的界面开发工具 2.5 部署应用程序到Android手机 第3章 用户人机界面 3.1 更改与显示文字标签——TextView标签的使用 ...

    Android系统屏保

    在应用内部,你可以提供一个设置入口,调用`WallpaperManager`的`setWallpaper()`或`setLiveWallpaper()`方法来设置屏保。 7. **文件名列表`PhotoTable`**:这个文件名可能指的是存储照片数据的数据库表,用于记录...

    Google Android SDK开发范例大全(完整版附部分源码).pdf

    Google Android SDK开发范例大全(完整版) 包含部分书中源码 目录 第1章 了解.深入.动手做. 1.1 红透半边天的Android 1.2 本书目的及涵盖范例范围 1.3 如何阅读本书 1.4 使用本书范例 1.5 参考网站 第2章 ...

    sw.rar_android

    通过调用其 setWallpaper() 或 setBitmap() 方法,应用能够将指定的图片设置为设备的锁屏或主屏幕壁纸。如果"sw"应用还支持动态壁纸,那么它可能利用了LiveWallpaper服务,这是一种特殊的壁纸类型,能够在屏幕上显示...

    Android 设置手机屏幕壁纸(桌面背景).rar

    Android 设置手机屏幕壁纸,不能就是大家熟悉的桌面背景,点击按钮,即可更换手机背景图片,整个功能的实现,封装在一个按钮事件中,以下是相关的代码片段:  Button bbjt;//设置背景图按钮  EditText etwz;//网站...

    android 壁纸系列 小猪佩奇

    用户选择壁纸后,可以调用 WallpaperManager 类的 setWallpaper() 或 setLiveWallpaper() 方法来设置壁纸。前者用于静态壁纸,后者用于动态壁纸。如果需要支持更换锁屏壁纸,同样需要调用 WallpaperManager 的相应...

    android设置壁纸

    3. **设置壁纸**:Android提供了`setWallpaper()`方法,通过`Context`对象调用,将`Bitmap`对象设置为壁纸。有三个不同类型的壁纸可以设置:主屏幕壁纸、锁屏壁纸和联系人壁纸,分别对应` WallpaperManager`的`...

    Android 动态壁纸源码.zip源码资源下载

    6. **设置和配置**:在`setWallpaper()`或`setLiveWallpaper()`方法中,用户可以将你的动态壁纸设置为当前壁纸。同时,你还可以提供一个设置界面让用户自定义壁纸的参数。 7. **优化性能**:由于动态壁纸一直在后台...

    Android设置桌面背景图片的实现方法

    在Android开发中,设置桌面背景图片是常见的需求之一,它涉及到对用户界面的自定义以及权限管理。下面将详细介绍如何实现这一功能。 首先,我们来看标题和描述中提到的实现方法。Android系统允许应用程序设置壁纸,...

Global site tag (gtag.js) - Google Analytics