編輯:關於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) {
HashSet keep = 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();
}
}
});
}
}
Android中測試框架使用簡介
測試好的程序是測出來的。測試的目的:盡可能多的測試出程序中的bug。測試分為黑盒測試:測試業務邏輯白盒測試:測試邏輯方法。一般是寫一段腳本代碼,通過腳本代碼去調用業務邏輯
Android 開源日志庫 Logger 使用教程
1.Logger 是什麼在我們日常的開發中,肯定是少不了要和 Log 打交道,回想一下我們是怎麼使用 Log 的:先定義一個靜態常量 TAG,TAG 的值通常是當前類的類
Android編譯系統(二)-mm編譯單個模塊
因為Android的編譯系統不同於Linux Kernel的遞歸式的編譯系統,它的編譯系統是一種稱之為independent的模式,每個模塊基本獨立(它有可能依賴其他模塊
Android onTouchEvent方法
Android中監聽觸摸事件是onTouchEvent方法,它的參數為MotionEvent,下面列舉MotionEvent的一些常用的方法: getPointerC