編輯:關於Android編程
AppWidget 通過內存共享進行數據通訊.原理圖如下:
1.創建一個BroadcastReceiver,繼承AppWidgetProvider.
2.在AndroidManifest.xml中配置如下:下面給出官網例子是必須的.
3.提供一個
4.定義appwidget的樣式.定義一個layout文件做為布局文件 ,並配置在上面intialLayout屬性中.
5.當用戶點擊選取添加某個小部件.首先獲取appWidgetId,並打開一個選取小部件的Activity
6.選取後,通過appWidgetId獲取appWidgetInfo,並轉化為LauncherAppWidgetInfo對象,並添加到workspace中.
當然,這段時間包括了appwidget的定位.其添加源碼如下:
private void completeAddAppWidget(Intent data, CellLayout.CellInfo cellInfo) { Bundle extras = data.getExtras(); int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); if (LOGD) Log.d(TAG, dumping extras content= + extras.toString()); AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); // Calculate the grid spans needed to fit this widget CellLayout layout = (CellLayout) mWorkspace.getChildAt(cellInfo.screen); int[] spans = layout.rectToCell(appWidgetInfo.minWidth, appWidgetInfo.minHeight); // Try finding open space on Launcher screen final int[] xy = mCellCoordinates; if (!findSlot(cellInfo, xy, spans[0], spans[1])) { if (appWidgetId != -1) mAppWidgetHost.deleteAppWidgetId(appWidgetId); return; } // Build Launcher-specific widget info and save to database LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId); launcherInfo.spanX = spans[0]; launcherInfo.spanY = spans[1]; LauncherModel.addItemToDatabase(this, launcherInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, mWorkspace.getCurrentScreen(), xy[0], xy[1], false); if (!mRestoring) { mDesktopItems.add(launcherInfo); // Perform actual inflation because we're live launcherInfo.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo); launcherInfo.hostView.setAppWidget(appWidgetId, appWidgetInfo); launcherInfo.hostView.setTag(launcherInfo); mWorkspace.addInCurrentScreen(launcherInfo.hostView, xy[0], xy[1], launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked()); } }總結:當我們執行完前3步,系統即會根據用戶選擇創建小部件.
--更新AppWidget界面,其原理如下:
1AppWidgetManager發送廣播傳遞ID.
void updateProvidersForPackageLocked(String pkgName) { HashSetkeep = new HashSet (); Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE); intent.setPackage(pkgName); List broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA); // add the missing ones and collect which ones to keep int N = broadcastReceivers == null ? 0 : broadcastReceivers.size(); for (int i=0; i 0) { int[] appWidgetIds = getAppWidgetIds(p); // Reschedule for the new updatePeriodMillis (don't worry about handling // it specially if updatePeriodMillis didn't change because we just sent // an update, and the next one will be updatePeriodMillis from now). cancelBroadcasts(p); registerForBroadcastsLocked(p, appWidgetIds); // If it's currently showing, call back with the new AppWidgetProviderInfo. for (int j=0; j =0; i--) { Provider p = mInstalledProviders.get(i); if (pkgName.equals(p.info.provider.getPackageName()) && !keep.contains(p.info.provider.getClassName())) { removeProviderLocked(i, p); } } }
2.用戶自定義AppwidgetProvider的onUpdate()接收數據.並通過Manager更新界面.(如下,官網給出了2個操作,1更新界面 2.點擊小部件操作)
public class ExampleAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { final int N = appWidgetIds.length; // Perform this loop procedure for each App Widget that belongs to this provider for (int i=0; i--Updating the App Widget from the configuration Activity(通過配置選項更改APPwidget界面,當Appwidget創建時,先進入該Activity進行判斷)
1.創建Activity並在AndroidManifest.xml裡面配置:
2.在appwidget的配置xml裡面增加屬性:
android:configure=org.lean.ConfigureActivity
3.在Activity中操作,1>根據配置修改遠程界面,2>跳轉回選擇的activity並由他關閉選擇Activity並顯示Launcher界面
package org.lean; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.EditText; import android.widget.RemoteViews; /** * * * @author Lean @date:2014-8-27 */ public class ConfigureActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.configure_view); findViewById(R.id.button1).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int appwidgetId=getIntent().getExtras().getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,AppWidgetManager.INVALID_APPWIDGET_ID); if (appwidgetId!=AppWidgetManager.INVALID_APPWIDGET_ID) { //修改遠程界面 EditText editText=(EditText) findViewById(R.id.editText1); String currenEtStr=editText.getText().toString(); RemoteViews views=new RemoteViews(ConfigureActivity.this.getPackageName(), R.layout.layout_widget); views.setTextViewText(R.id.btn,currenEtStr); AppWidgetManager manager=AppWidgetManager.getInstance(ConfigureActivity.this); manager.updateAppWidget(appwidgetId, views); //返回activity Intent reIntent=new Intent(); reIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,appwidgetId); setResult(RESULT_OK,reIntent); finish(); } } }); } }
測試好的程序是測出來的。測試的目的:盡可能多的測試出程序中的bug。測試分為黑盒測試:測試業務邏輯白盒測試:測試邏輯方法。一般是寫一段腳本代碼,通過腳本代碼去調用業務邏輯
1.Logger 是什麼在我們日常的開發中,肯定是少不了要和 Log 打交道,回想一下我們是怎麼使用 Log 的:先定義一個靜態常量 TAG,TAG 的值通常是當前類的類
因為Android的編譯系統不同於Linux Kernel的遞歸式的編譯系統,它的編譯系統是一種稱之為independent的模式,每個模塊基本獨立(它有可能依賴其他模塊
Android中監聽觸摸事件是onTouchEvent方法,它的參數為MotionEvent,下面列舉MotionEvent的一些常用的方法: getPointerC