編輯:高級開發
<manifest XMLns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.weatherlistwidget">
<uses-sdk android:minSdkVersion="11" />
<application android:label="Weather Widget Sample">
<receiver android:name="WeatherWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@XML/widgetinfo" />
</receiver>
<service android:name="WeatherWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
<provider android:name="WeatherDataProvider"
android:authoritIEs="com.example.android.weatherlistwidget.provider" />
</application>
</manifest>
這裡WeatherDataProvider.Java的源碼為主要是ContentProvider相關的處理,這裡作為appWidget的receiver
class WeatherDataPoint {
String city; //城市
int degrees; //度數
WeatherDataPoint(String c, int d) {
city = c;
degrees = d;
}
}
public class WeatherDataProvider extends ContentProvider {
public static final Uri CONTENT_URI =
Uri.parse("content://com.example.android.weatherlistwidget.provider");
public static class Columns {
public static final String ID = "_id";
public static final String CITY = "city";
public static final String TEMPERATURE = "temperature";
}
private static final ArrayList<WeatherDataPoint> sData = new ArrayList<WeatherDataPoint>();
@Override
public boolean onCreate() {
sData.add(new WeatherDataPoint("San Francisco", 13));
sData.add(new WeatherDataPoint("New York", 1));
sData.add(new WeatherDataPoint("Seattle", 7));
sData.add(new WeatherDataPoint("Boston", 4));
sData.add(new WeatherDataPoint("Miami", 22));
sData.add(new WeatherDataPoint("Toronto", -10));
sData.add(new WeatherDataPoint("Calgary", -13));
sData.add(new WeatherDataPoint("Tokyo", 8));
sData.add(new WeatherDataPoint("Kyoto", 11));
sData.add(new WeatherDataPoint("London", -1));
sData.add(new WeatherDataPoint("Nomanisan", 27));
return true;
}
@Override
public synchronized Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
assert(uri.getPathSegments().isEmpty());
final MatrixCursor c = new MatrixCursor(
new String[]{ Columns.ID, Columns.CITY, Columns.TEMPERATURE });
for (int i = 0; i < sData.size(); ++i) {
final WeatherDataPoint data = sData.get(i);
c.addRow(new Object[]{ new Integer(i), data.city, new Integer(data.degrees) });
}
return c;
}
@Override
public String getType(Uri uri) {
return "vnd.android.cursor.dir/vnd.weatherlistwidget.citytemperature";
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return 0;
}
@Override
public synchronized int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
assert(uri.getPathSegments().size() == 1);
final int index = Integer.parseInt(uri.getPathSegments().get(0));
final MatrixCursor c = new MatrixCursor(
new String[]{ Columns.ID, Columns.CITY, Columns.TEMPERATURE });
assert(0 <= index && index < sData.size());
final WeatherDataPoint data = sData.get(index);
data.degrees = values.getAsInteger(Columns.TEMPERATURE);
getContext().getContentResolver().notifyChange(uri, null);
return 1;
}
}
上面可以看到,對於插入和刪除沒有做過多的處理,對於天氣更新給出了詳細的解決方法。
有關 WeatherWidgetProvider.Java 主要是appWidget的核心,為provider
class WeatherDataProviderObserver extends ContentObserver { //監控數據庫的變化
private AppWidgetManager mAppWidgetManager;
private ComponentName mComponentName;
WeatherDataProviderObserver(AppWidgetManager mgr, ComponentName cn, Handler h) {
super(h);
mAppWidgetManager = mgr;
mComponentName = cn;
}
@Override
public void onChange(boolean selfChange) {
mAppWidgetManager.notifyAppWidgetVIEwDataChanged(
mAppWidgetManager.getAppWidgetIds(mComponentName), R.id.weather_list);
}
}
public class WeatherWidgetProvider extends AppWidgetProvider {
public static String CLICK_ACTION = "com.example.android.weatherlistwidget.CLICK";
public static String REFRESH_ACTION = "com.example.android.weatherlistwidget.REFRESH";
public static String EXTRA_CITY_ID = "com.example.android.weatherlistwidget.city";
private static HandlerThread sWorkerThread;
private static Handler sWorkerQueue;
private static WeatherDataProviderObserver sDataObserver;
public WeatherWidgetProvider() {
sWorkerThread = new HandlerThread("WeatherWidgetProvider-worker"); //開一個線程,這裡用到了HandlerThread
sWorkerThread.start();
sWorkerQueue = new Handler(sWorkerThread.getLooper()); //不了解Thread的Looper可以看下這個例子比較簡單清晰
}
@Override
public void onEnabled(Context context) { //當appWidget添加到桌面上時
final ContentResolver r = context.getContentResolver();
if (sDataObserver == null) {
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
final ComponentName cn = new ComponentName(context, WeatherWidgetProvider.class);
sDataObserver = new WeatherDataProviderObserver(mgr, cn, sWorkerQueue);
r.registerContentObserver(WeatherDataProvider.CONTENT_URI, true, sDataObserver); //注冊監控數據庫變化的回調
}
}
@Override
public void onReceive(Context ctx, Intent intent) {
final String action = intent.getAction();
if (action.equals(REFRESH_ACTION)) { //接收數據庫改變的回調廣播
final Context context = ctx;
sWorkerQueue.removeMessages(0);
sWorkerQueue.post(new Runnable() {
@Override
public void run() {
final ContentResolver r = context.getContentResolver();
final Cursor c = r.query(WeatherDataProvider.CONTENT_URI, null, null, null,
null);
final int count = c.getCount();
final int maxDegrees = 96;
r.unregisterContentObserver(sDataObserver); //首先取消數據庫監控
for (int i = 0; i < count; ++i) {
final Uri uri = ContentUris.withAppendedId(WeatherDataProvider.CONTENT_URI, i);
final ContentValues values = new ContentValues();
values.put(WeatherDataProvider.Columns.TEMPERATURE,
new Random().nextInt(maxDegrees));
r.update(uri, values, null, null); //更新數據庫記錄層
}
r.registerContentObserver(WeatherDataProvider.CONTENT_URI, true, sDataObserver); //重新設置監視數據庫
final AppWidgetManager mgr = AppWidgetManager.getInstance(context);
final ComponentName cn = new ComponentName(context, WeatherWidgetProvider.class);
mgr.notifyAppWidgetVIEwDataChanged(mgr.getAppWidgetIds(cn), R.id.weather_list); //提示Widget有數據更新並刷新UI
}
});
} else if (action.equals(CLICK_ACTION)) {
final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
final String city = intent.getStringExtra(EXTRA_CITY_ID);
final String formatStr = ctx.getResources().getString(R.string.toast_format_string);
Toast.makeText(ctx, String.format(formatStr, city), Toast.LENGTH_SHORT).show();
}
super.onReceive(ctx, intent);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; ++i) {
final Intent intent = new Intent(context, WeatherWidgetService.class); //當桌面上有多個這個相同的appWidget需要分別處理
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
final RemoteViews rv = new RemoteVIEws(context.getPackageName(), R.layout.widget_layout);
rv.setRemoteAdapter(appWidgetIds[i], R.id.weather_list, intent);
rv.setEmptyView(R.id.weather_list, R.id.empty_vIEw);
final Intent onClickIntent = new Intent(context, WeatherWidgetProvider.class);
onClickIntent.setAction(WeatherWidgetProvider.CLICK_ACTION);
onClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME)));
final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 0,
onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setPendingIntentTemplate(R.id.weather_list, onClickPendingIntent);
final Intent refreshIntent = new Intent(context, WeatherWidgetProvider.class);
refreshIntent.setAction(WeatherWidgetProvider.REFRESH_ACTION);
final PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0,
refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.refresh, refreshPendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
對於WeatherWidgetService.Java這個Service集成於RemoteVIEwsService,主要是UI上的處理
public class WeatherWidgetService extends RemoteVIEwsService {
@Override
public RemoteViewsFactory onGetVIEwFactory(Intent intent) {
return new StackRemoteVIEwsFactory(this.getApplicationContext(), intent);
}
}
class StackRemoteViewsFactory implements RemoteViewsService.RemoteVIEwsFactory {
private Context mContext;
private Cursor mCursor;
private int mAppWidgetId;
public StackRemoteVIEwsFactory(Context context, Intent intent) {
mContext = context;
mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
public void onCreate() {
}
public void onDestroy() {
if (mCursor != null) {
mCursor.close();
}
}
public int getCount() {
return mCursor.getCount();
}
public RemoteViews getVIEwAt(int position) {
String city = "Unknown City";
int temp = 0;
if (mCursor.moveToPosition(position)) {
final int cityColIndex = mCursor.getColumnIndex(WeatherDataProvider.Columns.CITY);
final int tempColIndex = mCursor.getColumnIndex(
WeatherDataProvider.Columns.TEMPERATURE);
city = mCursor.getString(cityColIndex);
temp = mCursor.getInt(tempColIndex);
}
final String formatStr = mContext.getResources().getString(R.string.item_format_string);
final int itemId = (position % 2 == 0 ? R.layout.light_widget_item
: R.layout.dark_widget_item);
RemoteViews rv = new RemoteVIEws(mContext.getPackageName(), itemId);
rv.setTextVIEwText(R.id.widget_item, String.format(formatStr, temp, city));
final Intent fillInIntent = new Intent();
final Bundle extras = new Bundle();
extras.putString(WeatherWidgetProvider.EXTRA_CITY_ID, city);
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
return rv;
}
public RemoteViews getLoadingVIEw() {
return null;
}
public int getVIEwTypeCount() {
return 2;
}
public long getItemId(int position) {
return position;
}
public boolean hasStableIds() {
return true;
}
public void onDataSetChanged() {
if (mCursor != null) {
mCursor.close();
}
mCursor = mContext.getContentResolver().query(WeatherDataProvider.CONTENT_URI, null, null,
null, null);
}
}
Android 拖/放框架允許用戶將數據從一個View到另一個視圖在當前布局中使用圖形化的拖放動作。該框架包括以下三個重要組成部分,支持拖放功能:拖動事件類拖動監聽器輔助
谷歌傾力打造的android系統平台智能手機操作系統,而相應的終端OPhone也已經推出了近十款之多。那麼隨著谷歌及android系統可能面臨的變動,OPhone自然也
Google的開源android移動操作系統正在席卷全球智能手機市場,和蘋果不一樣,它對那些想將應用程序提交到iPhone App Store的開發人員有著嚴格的指導方
下面詳細的說明一下android問題,所謂的android:android是基於Linux內核的軟件平台和操作系統,早期由Google開發,後由開放手機聯盟Open H