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








你可能感兴趣的:(java,android,UP)