Android桌面Widget

来源:互联网 发布:mac 音乐 编辑:程序博客网 时间:2024/04/30 01:47

写这篇博客主要是为了纪念一下我转做App之后的第一个应用,当时确实很多都不懂,一点一点开始研究,虽然写的很一般,但是当时真的很用心在做,连续做了2周,每天加班都在10点以后,全公司最后走的就是我,现在想想真的不错。
这个应用的需求改了又改,改了又改,经过无数次的需求修改,终于确定下来了,首先桌面要有一个widget负责定时显示图片内容,图片地址给出来的很多张图片,每张图片的显示时间也不同,对应每个图片还有不同的消息内容,如果是应用那么就去打开应用,如果是网页就去打开网页,数据为每12小时获取一次,图片要在wifi的情况下获得,原本还有获得手机的各种状态,包括地理位置,mac地址,蓝牙地址,如果有卡的话要获得基站信息,ip地址等发给后台,而且时间很短,10分钟发一次,由于这样做太费电,所以后面的需求被拿掉了。
需求就这么多,说说实现吧,widget在开机时接收到开机广播,去拿图片,并使用handler做12小时延迟操作,拿到数据后,放到一个list里面,然后通过list里面的对象获得图片地址,然后去下载每张图片,保存在本地,如果下次拿到数据后图片已经有了就不再去下载。
有的同学会说还有什么下载现在网上N多的显示网络图片的框架,improt进来直接用多方便,对不起我到现在还不知道widget中imageview怎么来设置网络图片,至少我找到的还不支持这种设置,如果有同学做过,请千万告诉我,省得写download图片的代码,好了话不多说开始上代码。
如果你想在桌面上生成一个widget,那么在AndroidManifest里面需要定义一个receiver,并且包含meta-data为

        <receiver android:name=".LogoAppWidgetProvider">            <intent-filter>                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />                <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />                <action android:name="android.net.wifi.STATE_CHANGE" />            </intent-filter>            <meta-data                android:name="android.appwidget.provider"                android:resource="@xml/adv_widget_provider" />        </receiver>

这里面resource = @xml/adv_widget_provider就是用来获得布局的

<?xml version="1.0" encoding="utf-8"?><appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"    android:initialLayout="@layout/adv_service_layout"    android:minHeight="30dp"    android:minWidth="250dp"    android:previewImage="@drawable/ic_launcher" ></appwidget-provider>

简单说说第一行布局文件,用来绘制你的widget的形体,后面的就是宽高,最下面的是你这个widget在launcher里面注册的图标样式,其中我要吐槽一下,金立做的launcher实在是让人发指,定制的launcher的大小完全和其他手机不同,我在其他手机上面写一行的数据,到了他这就是2行,而且左右两边无法对齐,好了这不是重点。
@layout/adv_service_layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@android:color/transparent"    android:gravity="center"    android:orientation="vertical">    <ImageView        android:id="@+id/adv_imageview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:scaleType="fitXY" /></LinearLayout>

这个没什么了,就一个imageview
后面就是Java代码了,首先是Application

public class LogoApplication extends Application {    public static List<LogoInfo> logoinfolist = new ArrayList<LogoInfo>();    public static List<LogoInfo> tempLogoInfoList = new ArrayList<LogoInfo>();    public static int logoinfolistLength;    public static int logoeverytime;    public static RequestQueue queues;    public static String picPath = "/sdcard/LogoWidget/";    public static List<String> picNameList = new ArrayList<String>();    public void onCreate() {        super.onCreate();        queues = Volley.newRequestQueue(getApplicationContext());        mHandler.sendEmptyMessage(0);        startService(new Intent(LogoApplication.this, DownloadPicFromClient.class));    }    Handler mHandler = new Handler() {        public void handleMessage(Message msg) {            super.handleMessage(msg);            try {                startService(new Intent(LogoApplication.this, LogoService.class));            } catch (Exception e) {                mHandler.sendEmptyMessageDelayed(0, 12 * 60 * 60 * 1000);            }            mHandler.sendEmptyMessageDelayed(0, 12 * 60 * 60 * 1000);        }    };    public static RequestQueue getHttpQueues() {        return queues;    }}

代码没什么难度,这里用初始化Volley,然后生命一个Handler每12小时拿一次数据,
后面还要写一个

public class LogoAppWidgetProvider extends AppWidgetProvider {    private static final String TAG = "LogoAppWidgetProvider";    public static final String ACTION_APPWIDGET_UPDATE = "android.appwidget.action.APPWIDGET_UPDATE";    // android:debuggable="false"    @Override    public void onReceive(Context context, Intent intent) {        // TODO Auto-generated method stub        Intent stateintent = new Intent(context, LogoService.class);        context.startService(stateintent);    }    public void onUpdate(Context context, AppWidgetManager appWidgetManager,            int[] appWidgetIds) {    }    @Override    public void onDeleted(Context context, int[] appWidgetIds) {    }    @Override    public void onEnabled(Context context) {    }    @Override    public void onDisabled(Context context) {        //context.stopService(new Intent(context, LogoService.class));    }}

这个是保证Application启动之后wifi没有打开,一旦wifi打开程序会在重新去拿数据
DownloadPicFromClient.java

public class GetDataFromClient implements HttpResponseListener {    private final static String loadJson = "https://cloud.yuyutechnology.com/adserver/adversFetch.do?deviceId=123&init=true&advertuserId=7";//pro    // private final static String loadJson = "https://cloud888.yuyutechnology.com/adserver/adversFetch.do?deviceId=123&init=true&advertuserId=7";//test    private final static String TAG_CHECK = "tag_check";    public static GetDataFromClient getInstace() {        return new GetDataFromClient();    }    public static void getdataFromClient(Context context) {        if (CheckWifiConnect.isNetworkConnected(context)) {            if (CheckWifiConnect.isWifiConnected(context)) {                if (!CheckWifiConnect.isMobileConnected(context)) {                    VolleyRequest volleyRequest = new VolleyRequest();                    volleyRequest.setHttpResponseListener(getInstace());                    volleyRequest.RequestPost(loadJson, TAG_CHECK);                }            }        }    }    @Override    public void httpResponse(String data) {        LG.e(GetDataFromClient.class, data);        dataToObject(data);    }    public void dataToObject(String data) {        if (data == null)            return;        try {            JSONArray valarray = new JSONArray(data);            LogoApplication.logoinfolistLength = valarray.length();            LogoApplication.logoeverytime = Integer.parseInt(valarray.getJSONObject(0)                    .getString("adImageShowInterval"));            LogoApplication.tempLogoInfoList.clear();            for (int i = 0; i < valarray.length(); i++) {                JSONObject arr = valarray.getJSONObject(i);                LogoInfo advinfo = new LogoInfo();                advinfo.adAppActionPackageName = arr                        .optString("adAppActionPackageName");                advinfo.adAppActionClassName = arr                        .optString("adAppActionClassName");                advinfo.adBrowserAction = arr                        .optString("adBrowserAction");                advinfo.adImageUrl = arr.optString("adImageUrl");                LogoApplication.tempLogoInfoList.add(advinfo);            }            EventBus.getDefault().post(LogoApplication.tempLogoInfoList);        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    @Override    public void httpREsponseError(VolleyError error) {    }}

获得数据放入到一个静态的list里面后续下载图片以及播放图片都要用到,这里面拿到图片之后就使用EventBus发送通知去下载图片
DownloadPicFromClient.java

public class DownloadPicFromClient extends Service {    Context context;    public static int i = 0;    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public void onCreate() {        super.onCreate();        context = getApplicationContext();    }    @Override    public void onStart(Intent intent, int startId) {        super.onStart(intent, startId);        if (!EventBus.getDefault().isRegistered(this))            EventBus.getDefault().register(this);    }    public void onEventMainThread(List<LogoInfo> logoinfolist) {        if (CheckWifiConnect.isNetworkConnected(context)) {            if (CheckWifiConnect.isWifiConnected(context)) {                for (int i = 0; i < logoinfolist.size(); i++) {                    File file = new File(logoinfolist.get(i).adImageUrl.trim());                    String fileName = file.getName();                    File sdFile = new File(LogoApplication.picPath + fileName);                    boolean iAllPic = true;                    if (!sdFile.exists()) {                        iAllPic = false;                        MyAsynaTask mTask = new MyAsynaTask(logoinfolist.get(i));                        mTask.execute(logoinfolist.get(i).adImageUrl);                    } else {                        logoinfolist.get(i).downPicName = fileName;                    }                    if (iAllPic)                        EventBus.getDefault().post("play advertisement");                }            }        }    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        EventBus.getDefault().unregister(this);        startService(new Intent(this, LogoService.class));    }    public class MyAsynaTask extends AsyncTask<String, Integer, Bitmap> {        LogoInfo logoInfo;        public MyAsynaTask(LogoInfo logoInfo) {            this.logoInfo = logoInfo;        }        @Override        protected void onPreExecute() {            // TODO Auto-generated method stub            super.onPreExecute();        }        @Override        protected Bitmap doInBackground(String... params) {            // TODO Auto-generated method stub            Bitmap bitmap = null;            try {                URL url = new URL(params[0]);                HttpURLConnection connection = (HttpURLConnection) url                        .openConnection();                connection.setDoInput(true);                connection.connect();                InputStream inputStream = connection.getInputStream();                bitmap = BitmapFactory.decodeStream(inputStream);                inputStream.close();            } catch (Exception e) {                // TODO: handle exception            }            return bitmap;        }        @Override        protected void onProgressUpdate(Integer... values) {            // TODO Auto-generated method stub        }        @Override        protected void onPostExecute(Bitmap result) {            // TODO Auto-generated method stub            super.onPostExecute(result);            boolean isFullBitmap = true;            this.logoInfo.picbitmap = result;            for (int j = 0; j < LogoApplication.tempLogoInfoList.size(); j++) {                if (LogoApplication.tempLogoInfoList.get(j).picbitmap == null) {                    isFullBitmap = false;                    break;                }            }            File file = new File(this.logoInfo.adImageUrl.trim());            String fileName = file.getName();            this.logoInfo.downPicName = fileName;            File sdFile = new File(LogoApplication.picPath + fileName);            if (!sdFile.exists() && result != null) {                LG.e(DownloadPicFromClient.class, "this.logoInfo.adImageUrl = " + this.logoInfo.adImageUrl);                saveCroppedImage(result, this.logoInfo.adImageUrl);            }            if (isFullBitmap) {                getFileCountAndName();                EventBus.getDefault().post("play advertisement");            }        }    }    private void saveCroppedImage(Bitmap bmp, String picUrl) {        File file = new File("/sdcard/LogoWidget");        if (!file.exists())            file.mkdir();        file = new File(("/sdcard/" + picUrl).trim());        String fileName = file.getName();        String mName = fileName.substring(0, fileName.lastIndexOf("."));        String sName = fileName.substring(fileName.lastIndexOf("."));        String newFilePath = LogoApplication.picPath + mName + sName;        file = new File(newFilePath);        if (fileIsExists(newFilePath)) {        } else {            try {                file.createNewFile();                FileOutputStream fos = new FileOutputStream(file);                bmp.compress(Bitmap.CompressFormat.JPEG, 50, fos);                fos.flush();                fos.close();            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public void getFileCountAndName() {        getFiles(LogoApplication.picPath);    }    public boolean fileIsExists(String strFile) {        try {            File f = new File(strFile);            if (!f.exists()) {                return false;            }        } catch (Exception e) {            return false;        }        return true;    }    private void getFiles(String string) {        // TODO Auto-generated method stub        File file = new File(string);        File[] files = file.listFiles();        for (int j = 0; j < files.length; j++) {            String name = files[j].getName();            if (files[j].isDirectory()) {                String dirPath = files[j].toString().toLowerCase();                Log.d("shifuqiang", "dirPath" + dirPath);                getFiles(dirPath + "/");            } else if (files[j].isFile() & name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".bmp") || name.endsWith(".gif") || name.endsWith(".jpeg")) {                Log.d("shifuqiang", "FileName===" + files[j].getName());                LogoApplication.picNameList.add(files[j].getName());                i++;            }        }        deletePicFromSDCard(LogoApplication.picNameList);    }    public void deletePicFromSDCard(List<String> picName) {        for (int i = 0; i < picName.size(); i++) {            boolean sdExitPic = false;            for (int j = 0; j < LogoApplication.tempLogoInfoList.size(); j++) {                if (LogoApplication.tempLogoInfoList.get(j).adImageUrl.contains((CharSequence) picName.get(i))) {                    sdExitPic = true;                    break;                }            }            if (!sdExitPic) {                deleteFileFromSDEx(picName.get(i));            }        }    }    public void deleteFileFromSDEx(String fileName) {        File deletefile = new File(LogoApplication.picPath + fileName);        deletefile.delete();    }}

代码虽然有点长,也是当时不太规范,所以写的乱七八糟的,但是通过名字都能知道是什么意思就不多说了
下载完之后就去播放图片

public class LogoService extends Service {    private static final String TAG = "LogoService";    RemoteViews views;    List<PackageInfo> list;    PackageManager packageManager;    Context mcontext;    int playcount;    @Override    public void onCreate() {        super.onCreate();        views = new RemoteViews(getPackageName(), R.layout.adv_service_layout);        packageManager = this.getPackageManager();        mcontext = getApplicationContext();    }    @Override    public void onStart(Intent intent, int startId) {        super.onStart(intent, startId);        GetDataFromClient.getdataFromClient(getApplicationContext());        if (!EventBus.getDefault().isRegistered(this))            EventBus.getDefault().register(this);        if (null == views)            views = new RemoteViews(getPackageName(), R.layout.adv_service_layout);    }    public void onEventMainThread(String playAdvertisement) {        if (null == views)            views = new RemoteViews(getPackageName(), R.layout.adv_service_layout);        views.setImageViewResource(R.id.adv_imageview, R.drawable.define_head);        if (mHander.hasMessages(0))            mHander.removeCallbacksAndMessages(null);        LogoApplication.logoinfolist.clear();        for (int i = 0; i < LogoApplication.tempLogoInfoList.size(); i++) {            LogoApplication.logoinfolist.add(LogoApplication.tempLogoInfoList.get(i));        }        if (LogoApplication.logoinfolist.size() == 1) {            refreshWidget();        } else if (LogoApplication.logoinfolist.size() > 1) {            mHander.sendEmptyMessage(0);        }    }    @Override    public IBinder onBind(Intent intent) {        return null;    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        return super.onStartCommand(intent, flags, startId);    }    @Override    public void onDestroy() {        super.onDestroy();        EventBus.getDefault().unregister(this);        mHander.removeCallbacksAndMessages(null);        startService(new Intent(this, LogoService.class));    }    Handler mHander = new Handler() {        public void handleMessage(Message msg) {            super.handleMessage(msg);            refreshWidget();            LG.e(LogoService.class, "handler post");            mHander.sendEmptyMessageDelayed(0, 5000);        }    };    public void getBitMapFromSDCard(String path, RemoteViews views) {        File mFile = new File(path);        if (mFile.exists()) {            Bitmap bitmap = BitmapFactory.decodeFile(path);            views.setImageViewBitmap(R.id.adv_imageview, bitmap);        }    }    public void refreshWidget() {        if (LogoApplication.logoinfolist == null                || LogoApplication.logoinfolist.isEmpty())            return;        if (null == views)            views = new RemoteViews(getPackageName(), R.layout.adv_service_layout);        if (LogoApplication.logoinfolist.get(playcount                % LogoApplication.logoinfolist.size()).picbitmap != null) {            views.setImageViewBitmap(R.id.adv_imageview, LogoApplication.logoinfolist.get(playcount                    % LogoApplication.logoinfolist.size()).picbitmap);        } else {            String sdPicPath = LogoApplication.picPath + LogoApplication.logoinfolist.get(playcount                    % LogoApplication.logoinfolist.size()).downPicName;            getBitMapFromSDCard(sdPicPath, views);        }        list = packageManager.getInstalledPackages(0);        boolean hasadvpackage = false;        for (PackageInfo packageInfo : list) {            if (packageInfo.packageName                    .equals(LogoApplication.logoinfolist.get(playcount                            % LogoApplication.logoinfolist.size()).adAppActionPackageName)) {                hasadvpackage = true;                break;            }        }        Intent mintented = new Intent();        if (hasadvpackage) {            PackageManager packageManager = this.getPackageManager();            mintented = packageManager.getLaunchIntentForPackage("com.yuyu.android.pcam");        } else {            Uri uri = Uri.parse(LogoApplication.logoinfolist.get(playcount                    % LogoApplication.logoinfolist.size()).adBrowserAction);            mintented.setAction(Intent.ACTION_VIEW);            mintented.setData(uri);        }        mintented.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);        PendingIntent pendingIntent = PendingIntent.getActivity(                getApplicationContext(), 0, mintented, 0);        views.setOnClickPendingIntent(R.id.adv_imageview, pendingIntent);        AppWidgetManager appWidgetManager = AppWidgetManager                .getInstance(getApplicationContext());        ComponentName componentName = new ComponentName(                getApplicationContext(), LogoAppWidgetProvider.class);        appWidgetManager.updateAppWidget(componentName, views);        playcount++;    }}

剩下的就是一些bean,接口类,和帮助类了
CheckWifiConnect.java

public static boolean isNetworkConnected(Context context) {        if (context != null) {            ConnectivityManager mConnectivityManager = (ConnectivityManager) context                    .getSystemService(Context.CONNECTIVITY_SERVICE);            NetworkInfo mNetworkInfo = mConnectivityManager                    .getActiveNetworkInfo();            if (mNetworkInfo != null) {                return mNetworkInfo.isAvailable();            }        }        return false;    }    public static boolean isWifiConnected(Context context) {        if (context != null) {            ConnectivityManager mConnectivityManager = (ConnectivityManager) context                    .getSystemService(Context.CONNECTIVITY_SERVICE);            NetworkInfo mWiFiNetworkInfo = mConnectivityManager                    .getNetworkInfo(ConnectivityManager.TYPE_WIFI);            if (mWiFiNetworkInfo != null) {                return mWiFiNetworkInfo.isConnected();            }        }        return false;    }    public static boolean isMobileConnected(Context context) {        if (context != null) {            ConnectivityManager mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);            NetworkInfo mMobileNetworkInfo = mConnectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);            if (mMobileNetworkInfo != null) {                return mMobileNetworkInfo.isConnected();            }        }        return false;    }

HttpResponseListener.java

public interface HttpResponseListener {    void httpResponse(String jsonObject);    void httpREsponseError(VolleyError error);}

LogoInfo.java

public class LogoInfo {    String adId;    String adName;    String adSerialNumber;    String advertiserId;    String adStartTime;    String adEndTime;    String adAppActionPackageName;    String adAppActionClassName;    String adAppStoreAction;    String adBrowserAction;    String adImageUrl;    String adImageShowInterval;    String adState;    String adDurationTime;    String DelayedStartTime;    String DelayedEndTime;    public Bitmap picbitmap;    public String downPicName;}

网络数据请求封装类VolleyRequest.java

public class VolleyRequest {    public StringRequest stringRequest;    public HttpResponseListener httpResponseListener;    public void setHttpResponseListener(            HttpResponseListener httpResponseListener) {        this.httpResponseListener = httpResponseListener;    }    public void RequestPost(String url, String tag) {        LogoApplication.getHttpQueues().cancelAll(tag);        stringRequest = new StringRequest(url,                  new Response.Listener<String>() {                      @Override                      public void onResponse(String response) {                        httpResponseListener.httpResponse(response);                    }                  }, new Response.ErrorListener() {                      @Override                      public void onErrorResponse(VolleyError error) {                           httpResponseListener.httpREsponseError(error);                    }                  });          stringRequest.setTag(tag);        LogoApplication.getHttpQueues().add(stringRequest);    }}
0 0