Widget

这两天都在解个bug,widget相关的,打开menu--->add--->widget--->FileManageer or Gallery.

bug现象:
这时,Gallery 能正常打开CropImage.java, 可以实现截图,在桌面正确生成一个图片;但是FileManager打开是,在桌面生成的是一个黑图。

先发patch吧,看了就明白了。

--- a/src/com/windriver/filemanager/FileManagerActivity.java
+++ b/src/com/windriver/filemanager/FileManagerActivity.java
@@ -16,6 +16,8 @@

 package com.windriver.filemanager;

+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.app.AlertDialog;
 import android.app.ListActivity;
 import android.content.Context;
@@ -78,6 +80,8 @@ public class FileManagerActivity extends ListActivity implements OnClickListener
     private TextView mTextPath;
     private Button mButtonBack;

+// private Bitmap image;

+
     private String mPath;
     private String mRootPath;
     private String mAction;
@@ -189,10 +193,24 @@ public class FileManagerActivity extends ListActivity implements OnClickListener
             if(action.equals(Intent.ACTION_MAIN)){
                 showInfo(f);
            } else if (action.equals(Intent.ACTION_GET_CONTENT)){
- Uri uri = Uri.fromFile(f);
- Log.v(TAG, "uri = " + uri.toString());
- setResult(RESULT_OK, new Intent().setData(uri));
- finish();
+ Bundle myExtras = intent.getExtras();
+ if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
+
+ try {
+ Bitmap image = BitmapFactory.decodeFile(mPath + "/" +name);  //打开sd卡中的图片,生成image。
+ Bitmap mBitmap = Bitmap.createBitmap(image,0,0,120,120); //缩放图片image,生成120x120的小图片,因为图片太大了,传不到widget里去。
+ image.recycle();    //用完回收内存。
+ Bundle extras = new Bundle();
+ extras.putParcelable("data", mBitmap);  //发送的内容。
+ setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras));   //发送信号inline-data,表示可以接收了。
+ } catch (Exception ex) {
+ }
+ } else {
+ Uri uri = Uri.fromFile(f);
+ Log.v(TAG, "uri = " + uri.toString());
+ setResult(RESULT_OK, new Intent().setData(uri));
+ }
+ finish();
            }
         }
     }
--
调试过程:

先是看了 FileManager
vendor/wrs/addons/FileManage r 里面的代码,知道了FileManager的工作原理。

然后看 packages/apps/Gallery3D/里面的内容,其中:
packages/apps/Gallery3D/src/com/cooliris/media/CropImage.java
因为打开Widget --->Gallery后,就进入CropImage.
里面的重要信息是:
private void onSaveClicked() {
        // CR: TODO!

        // TODO this code needs to change to use the decode/crop/encode single

        // step api so that we don't require that the whole (possibly large)

        // bitmap doesn't have to be read into memory

        if (mSaving)
            return;

        if (mCrop == null) {
            return;
        }

        mSaving = true;

        Rect r = mCrop.getCropRect();

        int width = r.width(); // CR: final == happy panda!

        int height = r.height();

        // If we are circle cropping, we want alpha channel, which is the

        // third param here.

        Bitmap croppedImage = Bitmap.createBitmap(width, height, mCircleCrop ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        {
            Canvas canvas = new Canvas(croppedImage);
            Rect dstRect = new Rect(0, 0, width, height);
            canvas.drawBitmap(mBitmap, r, dstRect, null);
        }

        if (mCircleCrop) {
            // OK, so what's all this about?

            // Bitmaps are inherently rectangular but we want to return

            // something that's basically a circle. So we fill in the

            // area around the circle with alpha. Note the all important

            // PortDuff.Mode.CLEAR.

            Canvas c = new Canvas(croppedImage);
            Path p = new Path();
            p.addCircle(width / 2F, height / 2F, width / 2F, Path.Direction.CW);
            c.clipPath(p, Region.Op.DIFFERENCE);
            c.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
        }

        // If the output is required to a specific size then scale or fill.

        if (mOutputX != 0 && mOutputY != 0) {
            if (mScale) {
                // Scale the image to the required dimensions.

                Bitmap old = croppedImage;
                croppedImage = Util.transform(new Matrix(), croppedImage, mOutputX, mOutputY, mScaleUp);
                if (old != croppedImage) {
                    old.recycle();
                }
            } else {

                                                   /*
                 * Don't scale the image crop it to the size requested. Create
                 * an new image with the cropped image in the center and the
                 * extra space filled.
                 */

                // Don't scale the image but instead fill it so it's the

                // required dimension

                Bitmap b = Bitmap.createBitmap(mOutputX, mOutputY, Bitmap.Config.RGB_565);
                Canvas canvas = new Canvas(b);

                Rect srcRect = mCrop.getCropRect();
                Rect dstRect = new Rect(0, 0, mOutputX, mOutputY);

                int dx = (srcRect.width() - dstRect.width()) / 2;
                int dy = (srcRect.height() - dstRect.height()) / 2;

                // If the srcRect is too big, use the center part of it.

                srcRect.inset(Math.max(0, dx), Math.max(0, dy));

                // If the dstRect is too big, use the center part of it.

                dstRect.inset(Math.max(0, -dx), Math.max(0, -dy));

                // Draw the cropped bitmap in the center.

                canvas.drawBitmap(mBitmap, srcRect, dstRect, null);

                // Set the cropped bitmap as the new bitmap.

                croppedImage.recycle();
                croppedImage = b;
            }
        }

        // Return the cropped image directly or save it to the specified URI.

        Bundle myExtras = getIntent().getExtras();
        if (myExtras != null && (myExtras.getParcelable("data") != null || myExtras.getBoolean("return-data"))) {
            Bundle extras = new Bundle();
            extras.putParcelable("data", croppedImage);
            setResult(RESULT_OK, (new Intent()).setAction("inline-data").putExtras(extras));  //这段实现了发送widget图片的机制。
            finish();
        } else {
            final Bitmap b = croppedImage;
            final Runnable save = new Runnable() {
                public void run() {
                    saveOutput(b);
                }
            };
            Util.startBackgroundJob(this, null, getResources().getString(R.string.saving_image), save, mHandler);
        }
    }

这样就把问题解决了。
但是解决之前,走了不少弯路,如下:
点开Widget,先运行AppWidgetPickActivity:
packages/apps/Settings/src/com/android/settings/AppWidgetPickActivity.java
就是选择widget 选项,这里选择photo frame.

然后进入PhotoAppWidgetProvider and  PhotoAppWidgetConfigure.java :
packages/apps/Gallery3D/src/com/cooliris/media/PhotoAppWidgetProvider.java
packages/apps/Gallery3D/src/com/cooliris/media/PhotoAppWidgetConfigure.java
这里有个重要的类:
static class PhotoDatabaseHelper extends SQLiteOpenHelper {
        private static final String DATABASE_NAME = "launcher.db";

        private static final int DATABASE_VERSION = 2;

        static final String TABLE_PHOTOS = "photos";
        static final String FIELD_APPWIDGET_ID = "appWidgetId";
        static final String FIELD_PHOTO_BLOB = "photoBlob";

        PhotoDatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

在PhotoAppWidgetConfigure.java中会用到,如下:
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && mAppWidgetId != -1) {
            // Store the cropped photo in our database

            Bitmap bitmap = (Bitmap) data.getParcelableExtra("data");

            PhotoDatabaseHelper helper = new PhotoDatabaseHelper(this);
            if (helper.setPhoto(mAppWidgetId, bitmap)) {
                resultCode = Activity.RESULT_OK;

                // Push newly updated widget to surface

                RemoteViews views PhotoAppWidgetProvider=.buildUpdate(this, mAppWidgetId, helper);
                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
                appWidgetManager.updateAppWidget(new int[] { mAppWidgetId }, views);
            }
            helper.close();
        } else {
            resultCode = Activity.RESULT_CANCELED;
        }

        // Make sure we pass back the original mAppWidgetId

        Intent resultValue = new Intent();
        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
        setResult(resultCode, resultValue);
        finish();
    }
开始一直以为是这里进行图片返回,一直没弄出来。

这里涉及framework里的一个widget类,AppWidgetManager:
frameworks/base/core/java/android/appwidget/AppWidgetManager.java

这之后就让选择 Gallery 或者 FileManager. 运行相应的程序了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值