您的位置:首页 > 移动开发

让自己的Android应用支持appwidget

2017-06-27 12:49 423 查看
经常看到一些教程教你如何写appwidget,但是,你知道你的appwidget是如何被添加到桌面上的吗?

        一般的,如果是做桌面的童鞋,基本上都会让自己的桌面支持appwidget。下面说说如何实现。

        首先是得定义一个承载appwidget的容器,系统的Launcher里面是用的CellLayout,实现的很不错。我这里就用一个简单的自定义ViewGroup来搞定,它是以长按的坐标处为要添加的appwidget的起始位置,简单点说就是按到哪儿就添加到哪儿。

Java代码  


package chroya.demo.widget;  

  

import android.content.Context;  

import android.view.MotionEvent;  

import android.view.View;  

import android.view.ViewGroup;  

  

/** 

 * 承载widget的容器 

 * @author chroya 

 */  

public class WidgetLayout extends ViewGroup {  

    //存放touch的坐标  

    private int[] cellInfo = new int[2];  

    private OnLongClickListener mLongClickListener;   

  

    public WidgetLayout(Context context) {  

        super(context);  

        mLongClickListener = new OnLongClickListener() {  

              

            @Override  

            public boolean onLongClick(View v) {  

                  

                return false;  

            }  

        };  

    }  

      

    public void addInScreen(View child, int width, int height) {  

        LayoutParams lp = new LayoutParams(width, height);  

        lp.x = cellInfo[0];  

        lp.y = cellInfo[1];  

        child.setOnLongClickListener(mLongClickListener);  

        addView(child, lp);  

    }  

      

    @Override  

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);  

        LayoutParams lp;  

        for(int index=0; index<getChildCount(); index++) {  

            lp = (LayoutParams) getChildAt(index).getLayoutParams();  

            getChildAt(index).measure(  

                    MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, lp.width),   

                    MeasureSpec.makeMeasureSpec(MeasureSpec.EXACTLY, lp.height));  

        }  

    }  

      

    @Override  

    public boolean dispatchTouchEvent(MotionEvent event) {  

        cellInfo[0] = (int)event.getX();  

        cellInfo[1] = (int)event.getY();  

        return super.dispatchTouchEvent(event);  

    }  

  

    @Override  

    protected void onLayout(boolean changed, int l, int t, int r, int b) {  

        LayoutParams lp;  

        for(int index=0; index<getChildCount(); index++) {  

            lp = (LayoutParams) getChildAt(index).getLayoutParams();  

            getChildAt(index).layout(lp.x, lp.y, lp.x+lp.width, lp.y+lp.height);  

        }  

    }  

      

    public static class LayoutParams extends ViewGroup.LayoutParams {  

        int x;  

        int y;  

  

        public LayoutParams(int width, int height) {  

            super(width, height);  

        }         

    }  

}  

 

        然后是重点了。还记得系统默认的桌面上,长按的时候出现的上下文菜单吗?里面有好几个选项,选择widget之后,会弹出一个已经安装的widget列表,选择一个widget之后,就会添加到桌面。我们可以把第一步去掉,长按之后,直接弹出已安装的widget列表,这是一个activity,用AppWidgetManager.ACTION_APPWIDGET_PICK这个Intent来启动,必须带上Extras,下面给出代码中有,不详叙。

Java代码  


package chroya.demo.widget;  

  

import static android.util.Log.d;  

  

import java.util.ArrayList;  

  

import android.app.Activity;  

import android.appwidget.AppWidgetHost;  

import android.appwidget.AppWidgetManager;  

import android.appwidget.AppWidgetProviderInfo;  

import android.content.ComponentName;  

import android.content.Intent;  

import android.os.Bundle;  

import android.view.View;  

import android.view.View.OnLongClickListener;  

  

/** 

 * 添加appwidget 

 * @author chroya 

 * 

 */  

public class Main extends Activity {  

    private AppWidgetHost mAppWidgetHost;  

    private AppWidgetManager mAppWidgetManager;  

    private WidgetLayout layout;      

      

    private static final int REQUEST_PICK_APPWIDGET = 1;  

    private static final int REQUEST_CREATE_APPWIDGET = 2;    

    private static final int APPWIDGET_HOST_ID = 0x100;  

    private static final String EXTRA_CUSTOM_WIDGET = "custom_widget";  

      

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

          

        mAppWidgetManager = AppWidgetManager.getInstance(getApplicationContext());  

        mAppWidgetHost = new AppWidgetHost(getApplicationContext(), APPWIDGET_HOST_ID);  

        //开始监听widget的变化  

        mAppWidgetHost.startListening();  

          

        layout = new WidgetLayout(this);  

        layout.setOnLongClickListener(new OnLongClickListener() {  

              

            @Override  

            public boolean onLongClick(View v) {  

                  

                addWidget();  

                return false;  

            }  

        });  

        setContentView(layout);  

    }  

      

    @Override  

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {  

        if (resultCode == RESULT_OK) {  

            switch (requestCode) {  

            case REQUEST_PICK_APPWIDGET:  

                addAppWidget(data);  

                break;  

            case REQUEST_CREATE_APPWIDGET:  

                completeAddAppWidget(data);  

                break;  

            }  

        } else if (requestCode == REQUEST_PICK_APPWIDGET &&  

                resultCode == RESULT_CANCELED && data != null) {  

            // Clean up the appWidgetId if we canceled  

            int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);  

            if (appWidgetId != -1) {  

                mAppWidgetHost.deleteAppWidgetId(appWidgetId);  

            }  

        }  

    }  

      

    /** 

     * 选中了某个widget之后,根据是否有配置来决定直接添加还是弹出配置activity 

     * @param data 

     */  

    private void addAppWidget(Intent data) {  

        int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);  

  

        String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET);  

        d("addAppWidget", "data:"+ customWidget);  

        if ("search_widget".equals(customWidget)) {  

            //这里直接将search_widget删掉了  

            mAppWidgetHost.deleteAppWidgetId(appWidgetId);  

        } else {  

            AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId);  

              

            d("addAppWidget", "configure:"+ appWidget.configure);  

            if (appWidget.configure != null) {  

                //有配置,弹出配置  

                Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);  

                intent.setComponent(appWidget.configure);  

                intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);  

  

                startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);  

            } else {  

                //没有配置,直接添加  

                onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data);  

            }  

        }  

    }  

      

    /** 

     * 请求添加一个新的widget 

     */  

    private void addWidget() {  

        int appWidgetId = mAppWidgetHost.allocateAppWidgetId();  

  

        Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK);  

        pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);  

        // add the search widget  

        ArrayList<AppWidgetProviderInfo> customInfo =  

                new ArrayList<AppWidgetProviderInfo>();  

        AppWidgetProviderInfo info = new AppWidgetProviderInfo();  

        info.provider = new ComponentName(getPackageName(), "XXX.YYY");  

        info.label = "Search";  

        info.icon = R.drawable.ic_search_widget;  

        customInfo.add(info);  

        pickIntent.putParcelableArrayListExtra(  

                AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo);  

        ArrayList<Bundle> customExtras = new ArrayList<Bundle>();  

        Bundle b = new Bundle();  

        b.putString(EXTRA_CUSTOM_WIDGET, "search_widget");  

        customExtras.add(b);  

        pickIntent.putParcelableArrayListExtra(  

                AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras);  

        // start the pick activity  

        startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET);  

    }      

      

    /** 

     * 添加widget 

     * @param data 

     */  

    private void completeAddAppWidget(Intent data) {  

        Bundle extras = data.getExtras();  

        int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);  

  

        d("completeAddAppWidget", "dumping extras content="+extras.toString());  

        d("completeAddAppWidget", "appWidgetId:"+ appWidgetId);  

        AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId);  

          

        View hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);  

          

        layout.addInScreen(hostView, appWidgetInfo.minWidth, appWidgetInfo.minHeight);          

    }  

}  

 

  

        需要注意的几点:

1。 必须调用AppWidgetHost的startListening方法来监听appwidget的状态变化,否则添加上去的appwidget不会更新的。

2。 需要override一个onActivityResult方法,来接收添加appwidget和appwidget的配置activity的返回值。

3。 启动AppWidgetManager.ACTION_APPWIDGET_PICK这个Intent,必须要给列表中加上自己定义的一个选项,否则出错。如本例中是用的Search。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: