广播接收器是应用程序组件,监听特定意图广播。根据android.content.Internet类中的定义,能够针对其编写一个接收器。要建立一个接收器,必须扩展android.content.BroadcastReceiver类或者其一个子类。 在类中必须提供OnReceive的方法的实现。
1 基于时钟的广播接收器
android自带有可以显示时钟的接收器。基于ACTION_TIME_TICK广播的时钟微件。意图动做是每分钟广播的,很适合适中。下面是一个广播接收器和一个活动的简单程勋。java
package com.example.broadcastreceiverdemo1; import java.util.Calendar; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.text.format.DateFormat; import android.util.Log; import android.view.Menu; import android.widget.TextView; public class MainActivity extends Activity { BroadcastReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void onResume() { super.onResume(); setTime(); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { setTime(); } }; IntentFilter intentFilter = new IntentFilter( Intent.ACTION_TIME_TICK); this.registerReceiver(receiver, intentFilter); } public void onPause() { this.unregisterReceiver(receiver); super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } private void setTime() { Calendar calendar = Calendar.getInstance(); CharSequence newTime = DateFormat.format( "kk:mm", calendar); TextView textView = (TextView) findViewById( R.id.textView1); textView.setText(newTime); } } //重要的部分是onReceive方法: @Override public void onReceive(Context context, Intent intent) { setTime(); } IntentFilter intentFilter = new IntentFilter( Intent.ACTION_TIME_TICK); this.registerReceiver(receiver, intentFilter);
2 取消通知
通知操做须要一个PendingInternet,而且能够对一个PendingInternet变成已发送广播,须要创建一个名为cancel_notification的用户定义意图操做。android
package com.example.cancelnotificationdemo; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { private static final String CANCEL_NOTIFICATION_ACTION = "cancel_notification"; int notificationId = 1002; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.cancel(notificationId); } }; IntentFilter filter = new IntentFilter(); filter.addAction(CANCEL_NOTIFICATION_ACTION); this.registerReceiver(receiver, filter); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } public void setNotification(View view) { Intent cancelIntent = new Intent("cancel_notification"); PendingIntent cancelPendingIntent = PendingIntent.getBroadcast(this, 100, cancelIntent, 0); Notification notification = new Notification.Builder(this) .setContentTitle("Stop Press") .setContentText( "Everyone gets extra vacation week!") .setSmallIcon(android.R.drawable.star_on) .setAutoCancel(true) .addAction(android.R.drawable.btn_dialog, "Dismiss", cancelPendingIntent) .build(); NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.notify(notificationId, notification); } public void clearNotification(View view) { NotificationManager notificationManager = (NotificationManager) getSystemService( NOTIFICATION_SERVICE); notificationManager.cancel(notificationId); } }
1.概念与相关属性方法:
AlarmManager:
一、AlarmManager,顾名思义,就是“提醒”,是Android中经常使用的一种系统级别的提示服务,在特定的时刻为咱们广播一个指定的Intent。简单的说就是咱们设定一个时间,而后在该时间到来时,AlarmManager为咱们广播一个咱们设定的Intent,一般咱们使用 PendingIntent,PendingIntent能够理解为Intent的封装包,简单的说就是在Intent上在加个指定的动做。在使用Intent的时候,咱们还须要在执行startActivity、startService或sendBroadcast才能使Intent有用。而PendingIntent的话就是将这个动做包含在内了。
定义一个PendingIntent对象。
PendingIntent pi = PendingIntent.getBroadcast(this,0,intent,0);
二、AlarmManager的经常使用方法有三个:
(1)set(int type,long startTime,PendingIntent pi);
该方法用于设置一次性闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟执行时间,第三个参数表示闹钟响应动做。
(2)setRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法用于设置重复闹钟,第一个参数表示闹钟类型,第二个参数表示闹钟首次执行时间,第三个参数表示闹钟两次执行的间隔时间,第三个参数表示闹钟响应动做。
(3)setInexactRepeating(int type,long startTime,long intervalTime,PendingIntent pi);
该方法也用于设置重复闹钟,与第二个方法类似,不过其两个闹钟执行的间隔时间不是固定的而已。
三、三个方法各个参数详悉:
(1)int type: 闹钟的类型,经常使用的有5个值:AlarmManager.ELAPSED_REALTIME、 AlarmManager.ELAPSED_REALTIME_WAKEUP、AlarmManager.RTC、 AlarmManager.RTC_WAKEUP、AlarmManager.POWER_OFF_WAKEUP。
AlarmManager.ELAPSED_REALTIME表示闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;
AlarmManager.ELAPSED_REALTIME_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC表示闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;
AlarmManager.POWER_OFF_WAKEUP表示闹钟在手机关机状态下也能正常进行提示功能,因此是5个状态中用的最多的状态之一,该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;
(2)long startTime: 闹钟的第一次执行时间,以毫秒为单位,能够自定义时间,不过通常使用当前时间。须要注意的是,本属性与第一个属性(type)密切相关,若是第一个参数对 应的闹钟使用的是相对时间(ELAPSED_REALTIME和ELAPSED_REALTIME_WAKEUP),那么本属性就得使用相对时间(相对于 系统启动时间来讲),好比当前时间就表示为:SystemClock.elapsedRealtime();若是第一个参数对应的闹钟使用的是绝对时间 (RTC、RTC_WAKEUP、POWER_OFF_WAKEUP),那么本属性就得使用绝对时间,好比当前时间就表示 为:System.currentTimeMillis()。
(3)long intervalTime:对于后两个方法来讲,存在本属性,表示两次闹钟执行的间隔时间,也是以毫秒为单位。
(4)PendingIntent pi: 绑定了闹钟的执行动做,好比发送一个广播、给出提示等等。PendingIntent是Intent的封装类。须要注意的是,若是是经过启动服务来实现闹钟提 示的话,PendingIntent对象的获取就应该采用Pending.getService(Context c,int i,Intent intent,int j)方法;若是是经过广播来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getBroadcast(Context c,int i,Intent intent,int j)方法;若是是采用Activity的方式来实现闹钟提示的话,PendingIntent对象的获取就应该采用 PendingIntent.getActivity(Context c,int i,Intent intent,int j)方法。若是这三种方法错用了的话,虽然不会报错,可是看不到闹钟提示效果。
AlarmManager具体用法:Calendar.getInstance():
pendingIntent:
PendingIntent的getActivity方法,第一个参数是上下文,没啥好说的,第二个参数 requestCode,这个后面说,第三个参数是 Intent,用来存储信息,第四个参数是对参数的操做标识,经常使用的就是FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT。当使用FLAG_UPDATE_CURRENT时:
PendingIntent.getActivity(context, 0, notificationIntent,PendingIntent.FLAG_CANCEL_CURRENT时);
FLAG_UPDATE_CURRENT会更新以前PendingIntent的消息,好比,你推送了消息1,并在其中的Intent中putExtra了一个值“ABC”,在未点击该消息前,继续推送第二条消息,并在其中的Intent中putExtra了一个值“CBA”,好了,这时候,若是你单击消息1或者消息2,你会发现,他俩个的Intent中读取过来的信息都是“CBA”,就是说,第二个替换了第一个的内容
当使用FLAG_CANCEL_CURRENT时:
依然是上面的操做步骤,这时候会发现,点击消息1时,没反应,第二条能够点击。
致使上面两个问题的缘由就在于第二个参数requestCode,当requestCode值同样时,后面的就会对以前的消息起做用,因此为了不影响以前的消息,requestCode每次要设置不一样的内容。git
1)ContentProvider简介
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就能够向其余应用共享其数据。虽然使用其余方法也能够对外共享数据,但数据访问方式会因数据存储的方式而不一样,如:采用文件方式对外共享数据,须要进行文件操做读写数据;采用sharedpreferences共享数据,须要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式。
2)Uri类简介
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
在Content Provider中使用的查询字符串有别于标准的SQL查询。不少诸如select, add, delete, modify等操做咱们都使用一种特殊的URI来进行,这种URI由3个部分组成, “content://”, 表明数据的路径,和一个可选的标识数据的ID。如下是一些示例URI:
content://media/internal/images 这个URI将返回设备上存储的全部图片
content://contacts/people/ 这个URI将返回设备上的全部联系人信息
content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)
尽管这种查询字符串格式很常见,可是它看起来仍是有点使人迷惑。为此,Android提供一系列的帮助类(在android.provider包下),里面包含了不少以类变量形式给出的查询字符串,这种方式更容易让咱们理解一点,所以,如上面content://contacts/people/45这个URI就能够写成以下形式:
Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);
而后执行数据查询:
Cursor cur = managedQuery(person, null, null, null);
2 建立一个内容提供者
ContentProvider为不一样的软件之间数据共享,提供统一的接口。并且ContentProvider是以相似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据,也就应该与从数据库中获取数据的操做基本同样,只不过是采用URI来表示外界须要访问的“数据库”。至于如何从URI中识别出外界须要的是哪一个“数据库”这就是Android底层须要作的事情了,也就是说,若是咱们想让其余的应用使用咱们本身程序内的数据,就可使用ContentProvider定义一个对外开放的接口,从而使得其余的应用可使用咱们本身应用中的文件、数据库内存储的信息。
内容提供者是android应用程序的基本构建块之一,它们封装数据并将封装的数据经过单一的ContentResolver接口提供给应用程序。当你须要在多个应用之间共享数据的时候就须要用到内容提供者。例如,手机中的联系人数据会被多个应用所用到因此必需要用内容提供者存储起来。若是你不须要在多个应用之间共享数据,你可使用一个数据库,直接经过SQLite数据库。 当经过content resolver发送一个请求时,系统会检查给定的URI并把请求传给有注册受权的Contentprovider。 UriMatcher类有助于解析uri。
须要实现的主要方法是:
public boolean onCreate() 在建立ContentProvider时调用
public Cursor query(Uri, String[], String, String[], String) 用于查询指定Uri的ContentProvider,返回一个Cursor
public Uri insert(Uri, ContentValues) 用于添加数据到指定Uri的ContentProvider中,(外部应用向ContentProvider中添加数据)
public int update(Uri, ContentValues, String, String[]) 用于更新指定Uri的ContentProvider中的数据
public int delete(Uri, String, String[]) 用于从指定Uri的ContentProvider中删除数据
public String getType(Uri) 用于返回指定的Uri中的数据的MIME类型
数据访问的方法(如:insert(Uri, ContentValues) and update(Uri, ContentValues, String, String[]))可能被多个线程同时调用,此时必须是线程安全的。其余方法(如: onCreate())只能被应用的主线程调用,它应当避免冗长的操做。ContentResolver(内容解析者)请求被自动转发到合适的内容提供者实例,因此子类不须要担忧跨进程调用的细节。
3 消费内容提供者
ContentResolver能够与任意内容提供者进行会话,与其合做来对全部相关交互通信进行管理。当外部应用须要对ContentProvider中的数据进行添加、删除、修改和查询操做时,可使用ContentResolver类来完成,要获取ContentResolver对象,可使用Context提供的getContentResolver()方法。ContentResolver cr = getContentResolver();在上面咱们提到ContentProvider能够向其余应用程序提供数据,与之对应的ContentResolver则负责获取ContentProvider提供的数据,修改、添加、删除更新数据等;
ContentResolver 类也提供了与ContentProvider类相对应的四个方法:
public Uri insert(Uri uri, ContentValues values) 该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs) 该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) 该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) 该方法用于从ContentProvider中获取数据。
这些方法的第一个参数为Uri,表明要操做的是哪一个ContentProvider和对其中的什么数据进行操做,假设给定的是 Uri.parse(“content://com.qstingda.provider.personprovider/contact/15”),那么将会对主机名为com.qstingda.provider.personprovider的ContentProvider进行操做,path为contact/15的数据,看到这若是你以前没有接触过ContentProvider确定一头雾水,没有关系,这很正常,等咱们把理论知识讲完后会有实例,相信你看过实例后就会很明白了。数据库
andoid开发学习之android定位
使用百度Android定位SDK必须注册GPS和网络使用权限。定位SDK采用GPS、基站、Wi-Fi信号进行定位。当应用程序向定位SDK发起定位请求时,定位SDK会根据应用的定位因素(GPS、基站、Wi-Fi信号)的实际状况(如是否开启GPS、是否链接网络、是否有信号等)来生成相应定位依据进行定位。
用户能够设置知足自身需求的定位依据:
若用户设置GPS优先,则优先使用GPS进行定位,若是GPS定位未打开或者没有可用位置信息,且网络链接正常,定位SDK则会返回网络定位(即Wi-Fi与基站)的最优结果。为了使得到的网络定位结果更加精确,请打开手机的Wi-Fi开关。
导入库文件
在使用百度定位SDKv4.0以前,咱们要下载最新的库文件,下载地址:点击下载相关库文件,将liblocSDK4.so文件拷贝到libs/armeabi目录下。将locSDK4.0.jar文件拷贝到工程的libs
LocationClient 定位SDK的核心类,LocationClient类必须在主线程中声明。须要Context类型的参数。Context须要时全进程有效的context,推荐用getApplicationConext获取全进程有效的context,咱们调用registerLocationListener(BDLocationListener)方法来注册定位监听接口,BDLocationListener里面有两个方法,onReceiveLocation()(接收异步返回的定位结果),onReceivePoi()(接收异步返回的POI查询结果,POI是“Point of Interest”的缩写,能够翻译成“信息点”,每一个POI包含四方面信息,名称、类别、经度、纬度、附近的酒店、饭店,商铺等信息。咱们能够叫它为“导航地图信息”,导航地图数据是整个导航产业的基石),咱们这里只须要重写onReceiveLocation就好了
BDLocation 封装了定位SDK的定位结果,在BDLocationListener的onReceive方法中获取。经过该类用户能够获取error code,位置的坐标,精度半径,地址等信息,对于其getLocType ()方法获取的error code一些状况api
package com.example.baidumapdemo; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.MeasureSpec; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.MKGeneralListener; import com.baidu.mapapi.map.LocationData; import com.baidu.mapapi.map.MKEvent; import com.baidu.mapapi.map.MapController; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationOverlay; import com.baidu.mapapi.map.PopupClickListener; import com.baidu.mapapi.map.PopupOverlay; import com.baidu.platform.comapi.basestruct.GeoPoint; public class MainActivity extends Activity { private Toast mToast; private BMapManager mBMapManager; private MapView mMapView = null; private MapController mMapController = null; /** * 定位SDK的核心类 */ private LocationClient mLocClient; /** * 用户位置信息 */ private LocationData mLocData; /** * 个人位置图层 */ private LocationOverlay myLocationOverlay = null; /** * 弹出窗口图层 */ private PopupOverlay mPopupOverlay = null; private boolean isRequest = false;//是否手动触发请求定位 private boolean isFirstLoc = true;//是否首次定位 /** * 弹出窗口图层的View */ private View mPopupView; private BDLocation location; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //使用地图sdk前需先初始化BMapManager,这个必须在setContentView()先初始化 mBMapManager = new BMapManager(this); //第一个参数是API key, //第二个参数是经常使用事件监听,用来处理一般的网络错误,受权验证错误等,你也能够不添加这个回调接口 mBMapManager.init("7ae13368159d6a513eaa7a17b9413b4b", new MKGeneralListenerImpl()); setContentView(R.layout.activity_main); //点击按钮手动请求定位 ((Button) findViewById(R.id.request)).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { requestLocation(); } }); mMapView = (MapView) findViewById(R.id.bmapView); //获取百度地图控件实例 mMapController = mMapView.getController(); //获取地图控制器 mMapController.enableClick(true); //设置地图是否响应点击事件 mMapController.setZoom(14); //设置地图缩放级别 mMapView.setBuiltInZoomControls(true); //显示内置缩放控件 mMapView.setTraffic(true); //设置交通讯息图 // mMapView.setSatellite(true); //设置卫星图 // mMapController.setOverlooking(-45); //设置地图俯视角度 ,范围:0~ -45 mPopupView = LayoutInflater.from(this).inflate(R.layout.pop_layout, null); //实例化弹出窗口图层 mPopupOverlay = new PopupOverlay(mMapView ,new PopupClickListener() { /** * 点击弹出窗口图层回调的方法 */ @Override public void onClickedPopup(int arg0) { //隐藏弹出窗口图层 mPopupOverlay.hidePop(); } }); //实例化定位服务,LocationClient类必须在主线程中声明 mLocClient = new LocationClient(getApplicationContext()); mLocClient.registerLocationListener(new BDLocationListenerImpl());//注册定位监听接口 /** * LocationClientOption 该类用来设置定位SDK的定位方式。 */ LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); //打开GPRS option.setAddrType("all");//返回的定位结果包含地址信息 option.setCoorType("bd09ll");//返回的定位结果是百度经纬度,默认值gcj02 option.setPriority(LocationClientOption.GpsFirst); // 设置GPS优先 option.setScanSpan(5000); //设置发起定位请求的间隔时间为5000ms option.disableCache(false);//禁止启用缓存定位 // option.setPoiNumber(5); //最多返回POI个数 // option.setPoiDistance(1000); //poi查询距离 // option.setPoiExtraInfo(true); //是否须要POI的电话和地址等详细信息 mLocClient.setLocOption(option); //设置定位参数 mLocClient.start(); // 调用此方法开始定位 //定位图层初始化 myLocationOverlay = new LocationOverlay(mMapView); //实例化定位数据,并设置在个人位置图层 mLocData = new LocationData(); myLocationOverlay.setData(mLocData); //添加定位图层 mMapView.getOverlays().add(myLocationOverlay); //修改定位数据后刷新图层生效 mMapView.refresh(); } /** * 定位接口,须要实现两个方法 * @author xiaanming * */ public class BDLocationListenerImpl implements BDLocationListener { /** * 接收异步返回的定位结果,参数是BDLocation类型参数 */ @Override public void onReceiveLocation(BDLocation location) { if (location == null) { return; } StringBuffer sb = new StringBuffer(256); sb.append("time : "); sb.append(location.getTime()); sb.append("\nerror code : "); sb.append(location.getLocType()); sb.append("\nlatitude : "); sb.append(location.getLatitude()); sb.append("\nlontitude : "); sb.append(location.getLongitude()); sb.append("\nradius : "); sb.append(location.getRadius()); if (location.getLocType() == BDLocation.TypeGpsLocation){ sb.append("\nspeed : "); sb.append(location.getSpeed()); sb.append("\nsatellite : "); sb.append(location.getSatelliteNumber()); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation){ sb.append("\naddr : "); sb.append(location.getAddrStr()); } Log.e("log", sb.toString()); MainActivity.this.location = location; mLocData.latitude = location.getLatitude(); mLocData.longitude = location.getLongitude(); //若是不显示定位精度圈,将accuracy赋值为0便可 mLocData.accuracy = location.getRadius(); mLocData.direction = location.getDerect(); //将定位数据设置到定位图层里 myLocationOverlay.setData(mLocData); //更新图层数据执行刷新后生效 mMapView.refresh(); if(isFirstLoc || isRequest){ //将给定的位置点以动画形式移动至地图中心 mMapController.animateTo(new GeoPoint( (int) (location.getLatitude() * 1e6), (int) (location .getLongitude() * 1e6))); showPopupOverlay(location); isRequest = false; } isFirstLoc = false; } /** * 接收异步返回的POI查询结果,参数是BDLocation类型参数 */ @Override public void onReceivePoi(BDLocation poiLocation) { } } //继承MyLocationOverlay重写dispatchTap方法 private class LocationOverlay extends MyLocationOverlay{ public LocationOverlay(MapView arg0) { super(arg0); } /** * 在“个人位置”坐标上处理点击事件。 */ @Override protected boolean dispatchTap() { //点击个人位置显示PopupOverlay showPopupOverlay(location); return super.dispatchTap(); } } /** * 显示弹出窗口图层PopupOverlay * @param location */ private void showPopupOverlay(BDLocation location){ TextView popText = ((TextView)mPopupView.findViewById(R.id.location_tips)); popText.setText("[个人位置]\n" + location.getAddrStr()); mPopupOverlay.showPopup(getBitmapFromView(popText), new GeoPoint((int)(location.getLatitude()*1e6), (int)(location.getLongitude()*1e6)), 15); } /** * 手动请求定位的方法 */ public void requestLocation() { isRequest = true; if(mLocClient != null && mLocClient.isStarted()){ showToast("正在定位......"); mLocClient.requestLocation(); }else{ Log.d("log", "locClient is null or not started"); } } /** * 显示Toast消息 * @param msg */ private void showToast(String msg){ if(mToast == null){ mToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); }else{ mToast.setText(msg); mToast.setDuration(Toast.LENGTH_SHORT); } mToast.show(); } /** * 将View转换成Bitmap的方法 * @param view * @return */ public static Bitmap getBitmapFromView(View view) { view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight()); view.buildDrawingCache(); Bitmap bitmap = view.getDrawingCache(); return bitmap; } /** * 经常使用事件监听,用来处理一般的网络错误,受权验证错误等 * @author xiaanming * */ public class MKGeneralListenerImpl implements MKGeneralListener{ /** * 一些网络状态的错误处理回调函数 */ @Override public void onGetNetworkState(int iError) { if (iError == MKEvent.ERROR_NETWORK_CONNECT) { showToast("您的网络出错啦!"); } } /** * 受权错误的时候调用的回调函数 */ @Override public void onGetPermissionState(int iError) { if (iError == MKEvent.ERROR_PERMISSION_DENIED) { showToast("API KEY错误, 请检查!"); } } } @Override protected void onResume() { //MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause() mMapView.onResume(); super.onResume(); } @Override protected void onPause() { //MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause() mMapView.onPause(); super.onPause(); } @Override protected void onDestroy() { //MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy() mMapView.destroy(); //退出应用调用BMapManager的destroy()方法 if(mBMapManager != null){ mBMapManager.destroy(); mBMapManager = null; } //退出时销毁定位 if (mLocClient != null){ mLocClient.stop(); } super.onDestroy(); } }
LocationClientOption 用来设置定位SDK的定位方式,好比设置打开GPS,设置是否须要地址信息,设置发起定位请求的间隔时间等等,参数设置完后调用LocationClient 的setLocOption方法
LocationOverlay MyLocationOverlay的子类,重写里面的dispatchTap()方法,显示弹出窗口图层PopupOverlay,调用mMapView.getOverlays().add(myLocationOverlay)就将个人位置图层添加到地图里面
PopupOverlay 弹出图层,这个类仍是比较简单,里面只有三个方法,hidePop() (隐藏弹出图层)showPopup(Bitmap pop, GeoPoint point, int yOffset) (显示弹出图层)和showPopup显示多张图片的重载方法,因为showPopup方法只接受Bitmap对象,因此咱们必须将咱们的弹出图层View对象转换成Bitmap对象,咱们调用getBitmapFromView方法就实现这一转换
BDLocationListener接口的onReceiveLocation(BDLocation location) 方法我还要重点讲解下,咱们会发现onReceiveLocation方法会反复执行,他执行的间隔跟LocationClientOption类的setScanSpan()方法设定的值有关,咱们设定的是5000毫秒,则onReceiveLocation方法每隔5秒执行一次,注意,当咱们设定的值大于1000(ms),定位SDK内部使用定时定位模式。调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。若是定位SDK根据定位依据发现位置没有发生变化,就不会发起网络请求,返回上一次定位的结果;若是发现位置改变,就进行网络请求进行定位,获得新的定位结果。若是你只须要定位一次的话,这个设置小于1000,或者不用设置就能够了,定时定位时,调用一次requestLocation,会定时监听到定位结果缓存