編輯:關於Android編程
本案例研究討論了如何將地圖和地理定位特性構建到 Android* 商務應用中,包括在 Google Maps* 上覆蓋商店位置,以及在設備進入商店地理圍欄鄰近區域時借助地理圍欄通知用戶。
在本案例研究中,我們將會把地圖和地理定位功能集成到基於 Android 平板電腦的餐館商務應用中(圖 1)。 用戶可以從主菜單項“位置和地理圍欄”訪問地理定位功能(圖 2)。

圖 1 餐館應用主界面

圖 2 浮出控件菜單項
在 Google Maps 上顯示商店位置<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+PC9wPgo8cD4KttTT2tK7v+7JzM7x06bTw7b40dSjrM/Uyr7JzLXq1Nq12M28yc+1xM671sO21NPDu6e3x7Oj1rG527rN09DTw6OozbwgM6OpoaMgR29vZ2xlIE1hcHMgQW5kcm9pZCBBUEkgv8nM4bmp0rvW1rzytaW1xLe9yr29qyBHb29nbGUgTWFwcyC8r7PJ1sEgQW5kcm9pZCDTptPDoaM8L3A+CjxwPgpHb29nbGUgTWFwcyBBbmRyb2lkIEFQSSB2MiA8YnI+CjwvcD4KPHA+CsrHIEdvb2dsZSBQbGF5ILf+zvEgQVBLILXE0ruyv7fWoaMgzqrBy7S0vajKudPDIEdvb2dsZSBNYXBzIEFuZHJvaWQgQVBJIHYyILXEIEFuZHJvaWQg06bTw6Os0OjSqs/C1NiyosXk1sMgR29vZ2xlIFBsYXkgt/7O8SBTREujrLvxyKEgQVBJIMPc1L+yotTa06bTw7XEIEFuZHJvaWRNYW5pZmVzdC54bWwgzsS8/tbQzO2808v50Oi1xMno1sPAtLbUv6q3oru3vrO9+NDQyejWw6GjPC9wPgo8cD4KytfPyKOsxOPQ6NKqsLTV1dLUz8LN+NW+yc+1xMu1w/fAtMno1sMgR29vZ2xlIFBsYXkgt/7O8SBTREujumh0dHA6Ly9kZXZlbG9wZXIuYW5kcm9pZC5jb20vZ29vZ2xlL3BsYXktc2VydmljZXMvc2V0dXAuaHRtbKGjPC9wPgo8cD4KyLu686OsxOPQ6NKqtNO5yLjov6q3osjL1LG/2NbGzKijqEdvb2dsZSBEZXZlbG9wZXJzIENvbnNvbGWjqcnPttTE47XEz+7Ev7340NDXorLhsqK78cih0ru49iBBUEkgw9zUv6O6aHR0cHM6Ly9jb25zb2xlLmRldmVsb3BlcnMuZ29vZ2xlLmNvbS9wcm9qZWN0oaMKIMTj0OjSqtTaIEFuZHJvaWRNYW5pZmVzdC54bWwgzsS8/tbQzO280yBBUEkgw9zUv6GjPC9wPgo8cD4KPGltZyBzcmM9"/uploadfile/Collfiles/20140724/2014072409390170.jpg" alt="\">
圖 3 餐館應用在谷歌地圖上顯示商店的位置。
01<uses-permissionandroid:name=”android.permission.INTERNET"/>02<uses-permissionandroid:name="android.permission.ACCESS_NETWORK_STATE"/>03<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>04<uses-permissionandroid:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>0507<uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATION"/>08<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/>09<uses-permissionandroid:name="android.permission.ACCESS_MOCK_LOCATION"/>1011<uses-feature12android:glEsVersion="0x00020000"13android:required="true"/>
代碼示例 1。 建議在使用 Google Maps Android API 的應用上指定的權限。 包括 “ACCESS_MOCK_LOCATION” 權限(僅當需要使用模擬位置對應用進行測試時使用)
我們同樣需要將在1<meta-data2android:name="com.google.android.gms.version"3android:value="@integer/google_play_services_version"/>45<meta-data6android:name="com.google.android.maps.v2.API_KEY"7android:value="copy your API Key here"/>
代碼示例 2。 指定 Google Play 服務版本和 API 密鑰 **
首先,在你的 activity 布局 xml 文件中,添加一個 MapFragment 元素(代碼示例 3)。
1<fragment2android:id="@+id/storelocationmap"3android:layout_width="fill_parent"4android:layout_height="fill_parent"5android:name="com.google.android.gms.maps.MapFragment"6/>
代碼示例 3。 在 Activity 布局中添加 MapFragment **
在你的 activity 類中,您可以檢索 Google Maps MapFragment 對象並在每個商店位置處繪制商店圖標。
01…02privatestaticfinalLatLng CHANDLER =newLatLng(33.455,-112.0668);03…04privatestaticfinalStoreLocation[] ALLRESTURANTLOCATIONS =newStoreLocation[] {05newStoreLocation(newLatLng(33.455,-112.0668),newString("Phoenix, AZ")),06newStoreLocation(newLatLng(33.5123,-111.9336),newString("SCOTTSDALE, AZ")),07newStoreLocation(newLatLng(33.3333,-111.8335),newString("Chandler, AZ")),08newStoreLocation(newLatLng(33.4296,-111.9436),newString("Tempe, AZ")),09newStoreLocation(newLatLng(33.4152,-111.8315),newString("Mesa, AZ")),10newStoreLocation(newLatLng(33.3525,-111.7896),newString("Gilbert, AZ"))11};12…13@Override14protectedvoidonCreate(Bundle savedInstanceState) {15super.onCreate(savedInstanceState);16setContentView(R.layout.geolocation_view);1718mMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.storelocationmap)).getMap();19mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(CHANDLER, ZOOM_LEVEL));20Drawable iconDrawable = getResources().getDrawable(R.drawable.ic_launcher);21Bitmap iconBmp = ((BitmapDrawable) iconDrawable).getBitmap();22for(intix =0; ix < ALLRESTURANTLOCATIONS.length; ix++) {23mMap.addMarker(newMarkerOptions()24.position(ALLRESTURANTLOCATIONS[ix].mLatLng)25.icon(BitmapDescriptorFactory.fromBitmap(iconBmp)));26}27…
代碼示例 4。 在 Google Maps 上繪制商店圖標 **
在我們的餐館應用中,我們能夠為每個商店位置定義地理圍欄。 當設備進入商店附近時,應用將會發送一條通知,如“您已進入最喜愛的餐館的附近!” (圖 4)。

圖 4 我們根據興趣點和半徑將地理圍欄定義為一個圓形范圍。
在 Android SDK 中,位置服務也是 Google Play 服務 APK 的一部分,位於 “Extras” 目錄下。
如要申請地理圍欄監控,首先我們需要在應用的清單文件中指定 “ACCESS_FINE_LOCATION” 權限,該操作我們已經在上一部分中完成。
此外,我們還需要查看 Google Play 服務的可用性(代碼示例 5 中的 checkGooglePlayServices() 方法)。 locationClient().connect() 調用與位置客戶端成功建立連接後,位置服務將會調用onConnected(Bundle
bundle) 函數,位置客戶端可通過該函數申請添加或刪除地理圍欄。
001publicclassGeolocationActivityextendsActivityimplements002GooglePlayServicesClient.ConnectionCallbacks003…004{005…006privateLocationClient mLocationClient;007008…009010staticclassStoreLocation {011publicLatLng mLatLng;012publicString mId;013StoreLocation(LatLng latlng, String id) {014mLatLng = latlng;015mId = id;016}017}018019@Override020protectedvoidonCreate(Bundle savedInstanceState) {021super.onCreate(savedInstanceState);022setContentView(R.layout.geolocation_view);023024mLocationClient =newLocationClient(this,this,this);025026// Create a new broadcast receiver to receive updates from the listeners and service027mGeofenceBroadcastReceiver =newResturantGeofenceReceiver();028029// Create an intent filter for the broadcast receiver030mIntentFilter =newIntentFilter();031032// Action for broadcast Intents that report successful addition of geofences033mIntentFilter.addAction(ACTION_GEOFENCES_ADDED);034035// Action for broadcast Intents that report successful removal of geofences036mIntentFilter.addAction(ACTION_GEOFENCES_REMOVED);037038// Action for broadcast Intents containing various types of geofencing errors039mIntentFilter.addAction(ACTION_GEOFENCE_ERROR);040041// All Location Services sample apps use this category042mIntentFilter.addCategory(CATEGORY_LOCATION_SERVICES);043044createGeofences();045046mRegisterGeofenceButton = (Button)findViewById(R.id.geofence_switch);047mGeofenceState = CAN_START_GEOFENCE;048049}050051@Override052protectedvoidonResume() {053super.onResume();054// Register the broadcast receiver to receive status updates055LocalBroadcastManager.getInstance(this).registerReceiver(056mGeofenceBroadcastReceiver, mIntentFilter);057}058059/**060* Create a Geofence list061*/062publicvoidcreateGeofences() {063for(intix=0; ix > ALLRESTURANTLOCATIONS.length; ix++) {064Geofence fence =newGeofence.Builder()065.setRequestId(ALLRESTURANTLOCATIONS[ix].mId)066.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)067.setCircularRegion(068ALLRESTURANTLOCATIONS[ix].mLatLng.latitude, ALLRESTURANTLOCATIONS[ix].mLatLng.longitude, GEOFENCERADIUS)069.setExpirationDuration(Geofence.NEVER_EXPIRE)070.build();071mGeofenceList.add(fence);072}073}074075// callback function when the mRegisterGeofenceButton is clicked076publicvoidonRegisterGeofenceButtonClick(View view) {077if(mGeofenceState == CAN_REGISTER_GEOFENCE) {078registerGeofences();079mGeofenceState = GEOFENCE_REGISTERED;080mGeofenceButton.setText(R.string.unregister_geofence);081mGeofenceButton.setClickable(true);082else{083unregisterGeofences();084mGeofenceButton.setText(R.string.register_geofence);085mGeofenceButton.setClickable(true);086mGeofenceState = CAN_REGISTER_GEOFENCE;087}088}089090privatebooleancheckGooglePlayServices() {091intresult = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);092if(result == ConnectionResult.SUCCESS) {093returntrue;094}095else{096Dialog errDialog = GooglePlayServicesUtil.getErrorDialog(097result,098this,099CONNECTION_FAILURE_RESOLUTION_REQUEST);100101if(errorDialog !=null) {102errorDialog.show();103}104}105returnfalse;106}107108109publicvoidregisterGeofences() {110111if(!checkGooglePlayServices()) {112113return;114}115mRequestType = REQUEST_TYPE.ADD;116117try{118// Try to add geofences119requestConnectToLocationClient();120}catch(UnsupportedOperationException e) {121// handle the exception122}123124}125126publicvoidunregisterGeofences() {127128if(!checkGooglePlayServices()) {129return;130}131132// Record the type of removal133mRequestType = REQUEST_TYPE.REMOVE;134135// Try to make a removal request136try{137mCurrentIntent = getRequestPendingIntent());138requestConnectToLocationClient();139140}catch(UnsupportedOperationException e) {141// handle the exception142}143}144145publicvoidrequestConnectToLocationServices ()throwsUnsupportedOperationException {146// If a request is not already in progress147if(!mRequestInProgress) {148mRequestInProgress =true;149150locationClient().connect();151}152else{153// Throw an exception and stop the request154thrownewUnsupportedOperationException();155}156}157158159/**160* Get a location client and disconnect from Location Services161*/162privatevoidrequestDisconnectToLocationServices() {163164// A request is no longer in progress165mRequestInProgress =false;166167locationClient().disconnect();168169if(mRequestType == REQUEST_TYPE.REMOVE) {170mCurrentIntent.cancel();171}172173}174175/**176* returns A LocationClient object177*/178privateGooglePlayServicesClient locationClient() {179if(mLocationClient ==null) {180181mLocationClient =newLocationClient(this,this,this);182}183returnmLocationClient;184185}186187/*188Called back from the Location Services when the request to connect the client finishes successfully. At this point, you can189request the current location or start periodic updates190*/191@Override192publicvoidonConnected(Bundle bundle) {193if(mRequestType == REQUEST_TYPE.ADD) {194// Create a PendingIntent for Location Services to send when a geofence transition occurs195mGeofencePendingIntent = createRequestPendingIntent();196197// Send a request to add the current geofences198mLocationClient.addGeofences(mGeofenceList, mGeofencePendingIntent,this);199200}201elseif(mRequestType == REQUEST_TYPE.REMOVE){202203mLocationClient.removeGeofences(mCurrentIntent,this);204}205}206…207}
代碼示例 5。 通過位置服務申請地理圍欄監控 **
位置服務申請通常是非阻塞或異步調用。 事實上,在上一部分的代碼示例 5 中,我們已經實施了這些函數中的一個:locationClient().connect() 調用和位置客戶端建立連接後,位置服務將會調用onConnected(Bundle
bundle) 函數。 代碼示例 6 列出了我們需要實施的其他位置回調函數。
001publicclassGeolocationActivityextendsActivityimplements002OnAddGeofencesResultListener,003OnRemoveGeofencesResultListener,004GooglePlayServicesClient.ConnectionCallbacks,005GooglePlayServicesClient.OnConnectionFailedListener {006…007008009@Override010publicvoidonDisconnected() {011mRequestInProgress =false;012mLocationClient =null;013}014015016017/*018* Handle the result of adding the geofences019*/020@Override021public void onAddGeofencesResult(int statusCode, String[] geofenceRequestIds) {022023// Create a broadcast Intent that notifies other components of success or failure024Intent broadcastIntent = new Intent();025026// Temp storage for messages027String msg;028029// If adding the geocodes was successful030if (LocationStatusCodes.SUCCESS == statusCode) {031032// Create a message containing all the geofence IDs added.033msg = getString(R.string.add_geofences_result_success,034Arrays.toString(geofenceRequestIds));035036// Create an Intent to broadcast to the app037broadcastIntent.setAction(ACTION_GEOFENCES_ADDED)038.addCategory(CATEGORY_LOCATION_SERVICES)039.putExtra(EXTRA_GEOFENCE_STATUS, msg);040// If adding the geofences failed041} else {042msg = getString(043R.string.add_geofences_result_failure,044statusCode,045Arrays.toString(geofenceRequestIds)046);047broadcastIntent.setAction(ACTION_GEOFENCE_ERROR)048.addCategory(CATEGORY_LOCATION_SERVICES)049.putExtra(EXTRA_GEOFENCE_STATUS, msg);050}051052LocalBroadcastManager.getInstance(this)053.sendBroadcast(broadcastIntent);054055// request to disconnect the location client056requestDisconnectToLocationServices();057}058059/*060* Implementation of OnConnectionFailedListener.onConnectionFailed061* If a connection or disconnection request fails, report the error062* connectionResult is passed in from Location Services063*/064@Override065publicvoidonConnectionFailed(ConnectionResult connectionResult) {066mInProgress =false;067if(connectionResult.hasResolution()) {068069try{070connectionResult.startResolutionForResult(this,071CONNECTION_FAILURE_RESOLUTION_REQUEST);072}073catch(SendIntentException e) {074// log the error075}076}077else{078Intent errorBroadcastIntent =newIntent(ACTION_CONNECTION_ERROR);079errorBroadcastIntent.addCategory(CATEGORY_LOCATION_SERVICES)080.putExtra(EXTRA_CONNECTION_ERROR_CODE,081connectionResult.getErrorCode());082LocalBroadcastManager.getInstance(this)083.sendBroadcast(errorBroadcastIntent);084}085}086087@Override088publicvoidonRemoveGeofencesByPendingIntentResult(intstatusCode,089PendingIntent requestIntent) {090091// Create a broadcast Intent that notifies other components of success or failure092Intent broadcastIntent =newIntent();093094// If removing the geofences was successful095if(statusCode == LocationStatusCodes.SUCCESS) {096
097
//
Set the action and add the result message
098
broadcastIntent.setAction(ACTION_GEOFENCES_REMOVED);
099
broadcastIntent.putExtra(EXTRA_GEOFENCE_STATUS,
100
getString(R.string.remove_geofences_intent_success));
101
102
}
103
else
{
104
//
removing the geocodes failed
105
106
107
//
Set the action and add the result message
108
broadcastIntent.setAction(ACTION_GEOFENCE_ERROR);
109
broadcastIntent.putExtra(EXTRA_GEOFENCE_STATUS,
110
getString(R.string.remove_geofences_intent_failure,
111
statusCode));
112
}
113
LocalBroadcastManager.getInstance(this)
114
.sendBroadcast(broadcastIntent);
115
116
//
request to disconnect the location client
117
requestDisconnectToLocationServices();
118
}
119
120
121
public
class
ResturantGeofenceReceiver extends
BroadcastReceiver {
122
123
124
@Override
125
public
void
onReceive(Context context, Intent intent) {
126
String
action = intent.getAction();
127
128
//
Intent contains information about errors in adding or removing geofences
129
if
(TextUtils.equals(action, ACTION_GEOFENCE_ERROR)) {
130
//
handleGeofenceError(context, intent);
131
}
132
else
if
(TextUtils.equals(action, ACTION_GEOFENCES_ADDED)
133
||
134
TextUtils.equals(action,
ACTION_GEOFENCES_REMOVED)) {
135
//
handleGeofenceStatus(context, intent);
136
}
137
else
if
(TextUtils.equals(action, ACTION_GEOFENCE_TRANSITION)) {
138
//
handleGeofenceTransition(context, intent);
139
}
140
else
{
141
//
handle error
142
}
143
144
}
145
}
146
147
Android中的系統服務(代理模式)
一,系統啟動Android設備的開機流程總得來分可以分為三部分:加載引導程序引導程序bootloader是開機運行的第一個小程序,因此它是針對特定的主板與芯片的。boot
微信理財通怎麼用 微信理財通收益如何查看
你現在還是把錢都存在余額寶?相信你也注意到,現在理財方式越來越多,余額寶的收益也越來越低,比如說財付通的理財通,性質類似於余額寶。現在微信也有理財通,收益還
Android四大組件之BroadcastReceiver(下)
(一)概述上節我們對BroadcastReceiver已經有了一個初步的了解了,知道兩種廣播類型:標准與有序, 動態或靜態注冊廣播接收者,監聽系統廣播,自己發送廣播!已經
Android的Handler機制
Android 的 Handler 機制(也有人叫消息機制)目的是為了跨線程通信,也就是多線程通信。之所以需要跨線程通信是因為在 Android 中主線程通常只負責 UI