安卓开发遇到的几个问题(网络定位,从网络获取所有省/市,SQLite,Service等)
来源:互联网 发布:广告投放算法好吃 编辑:程序博客网 时间:2024/03/28 20:09
//本文是作者原创文章,其中的代码部分引用了网上现有的demo,感谢大神们无私的奉献各种demo,转载请注明出处
今天在写公司的一个项目,其中用到了定位的功能,想到网上有很多现成的demo,兴致冲冲的找了很多demo,都没有想要的效果,网上现有的demo获取数据的方法大致分为两种:
<1> 将包含了地址信息的数据库文件(.db文件)存在项目的assets文件里面。
<2> 将地址信息放在arrays.xml文件里面,例如:
<string-array name="city"> <item>北京</item> <item>成都</item> <item>重庆</item> <item>广州</item> <item>杭州</item> <item>南京</item> <item>上海</item> <item>深圳</item> <item>天津</item> <item>武汉</item> <item>西安</item> </string-array>
然而这些都不是我想要的效果,Boss要求地址的数据在后期是可以修改的,
所以获取地址就必要链接网络服务器,在网上找了个仿美图的地址选择器,页面效果如下:
然而打开demo后就绝望了,
自动定位的功能只能看不能用就算了,用的竟然是第二种方法存数据…..
那岂不是说我得将300多条数据一点点的写到arrays.xml文件里面?于是仔细的看了该demo的代码,修改如下:
import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.os.Build;import android.os.Bundle;import android.text.Editable;import android.text.TextUtils;import android.text.TextWatcher;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.Window;import android.view.WindowManager;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.Button;import android.widget.GridView;import android.widget.ImageView;import android.widget.ListView;import android.widget.SectionIndexer;import android.widget.TextView;import android.widget.Toast;import com.amap.api.location.AMapLocation;import com.amap.api.location.AMapLocationClient;import com.amap.api.location.AMapLocationClientOption;import com.amap.api.location.AMapLocationListener;import com.example.myapplication.R;import com.example.myapplication.model.bean.CitySortModel;import com.example.myapplication.model.db.CityHelper;import com.example.myapplication.model.utils.ACache;import com.example.myapplication.model.utils.PortUtils;import com.example.myapplication.model.utils.SystemBarTintManager;import com.example.myapplication.view.activity.BaseActivity;import com.example.myapplication.view.selectcity.view.EditTextWithDel;import com.example.myapplication.view.selectcity.view.PinyinComparator;import com.example.myapplication.view.selectcity.view.PinyinUtils;import com.example.myapplication.view.selectcity.view.SideBar;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import org.xutils.common.Callback;import org.xutils.http.RequestParams;import org.xutils.x;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Collections;import java.util.Date;import java.util.List;/** 城市选择和定位* */public class CityActivity extends BaseActivity { private String TAG = "CityActivity"; private ListView sortListView; private SideBar sideBar; private TextView dialog, mTvTitle; private SortAdapter adapter; private EditTextWithDel mEtCityName; private List<CitySortModel> SourceDateList;//省份集合 private ImageView city_back;//返回键 private TextView city_commit;//确认 private ACache aCache;//缓存 private BroadcastMain receiver;//广播接收者 private Button button; private List<String> list; //声明AMapLocationClient类对象 public AMapLocationClient mLocationClient = null; //声明AMapLocationClientOption对象 public AMapLocationClientOption mLocationOption = null; //内部类,实现BroadcastReceiver public class BroadcastMain extends BroadcastReceiver { //必须要重载的方法,用来监听是否有广播发送 @Override public void onReceive(Context context, Intent intent) { //将收到的广播信息填充到标题栏 mTvTitle.setText(intent.getStringExtra("CITY")); } } private CityHelper helper;//存放城市信息的数据库 private SQLiteDatabase read; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /**************** * 沉浸式状态栏** * ************** * */ //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Window window = getWindow(); // // Translucent status bar // window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, // WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // SystemBarTintManager tintManager = new SystemBarTintManager(this); // tintManager.setStatusBarTintEnabled(true); // tintManager.setStatusBarTintResource(R.color.tomato);// 通知栏所需颜色 // } setContentView(R.layout.activity_city); //初始化广播接收者 receiver = new BroadcastMain(); //在代码中注册广播接收程序 IntentFilter filter = new IntentFilter(); filter.addAction("city.choose"); registerReceiver(receiver, filter); //初始化高德SDK定位配置 initLocationSDK(); //初始化控件 initViews(); } private void initLocaitonSDK(){ //初始化定位 mLocationClient = new AMapLocationClient(getApplicationContext()); //设置定位回调监听 mLocationClient.setLocationListener(mAMapLocationListener); //初始化AMapLocationClientOption对象 mLocationOption = new AMapLocationClientOption(); //设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。 mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); //获取一次定位结果: //该方法默认为false。 mLocationOption.setOnceLocation(true); //获取最近3s内精度最高的一次定位结果: //设置setOnceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。 // 如果设置其为true,setOnceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。 mLocationOption.setOnceLocationLatest(true); //设置定位间隔,单位毫秒,默认为2000ms,最低1000ms。 mLocationOption.setInterval(1000); //设置是否返回地址信息(默认返回地址信息) mLocationOption.setNeedAddress(true); //设置是否强制刷新WIFI,默认为true,强制刷新。 mLocationOption.setWifiActiveScan(false); //设置是否允许模拟位置,默认为false,不允许模拟位置 mLocationOption.setMockEnable(false); //单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。 mLocationOption.setHttpTimeOut(20000); //关闭缓存机制 mLocationOption.setLocationCacheEnable(false); //给定位客户端对象设置定位参数 mLocationClient.setLocationOption(mLocationOption); } //可以通过类implement方式实现AMapLocationListener接口,也可以通过创造接口类对象的方法实现 AMapLocationListener mAMapLocationListener = new AMapLocationListener() { @Override public void onLocationChanged(AMapLocation amapLocation) { if (amapLocation != null) { if (amapLocation.getErrorCode() == 0) { //解析amapLocation获取相应内容。 // amapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详 见定位类型表 // amapLocation.getLatitude();//获取纬度 // amapLocation.getLongitude();//获取经度 // amapLocation.getAccuracy();//获取精度信息 // amapLocation.getAddress();//地址,如果option中设置isNeedAddress为 // false,则没有此结果,网络定位结果中会有地址信息, // GPS定位不返回地址信息。 // amapLocation.getCountry();//国家信息 // amapLocation.getProvince();//省信息 String city = amapLocation.getCity();//城市信息 // amapLocation.getDistrict();//城区信息 //amapLocation.getStreet();//街道信息 // amapLocation.getStreetNum();//街道门牌号信息 // amapLocation.getCityCode();//城市编码 // amapLocation.getAdCode();//地区编码 // amapLocation.getAoiName();//获取当前定位点的AOI信息 // amapLocation.getBuildingId();//获取当前室内定位的建筑物Id // amapLocation.getFloor();//获取当前室内定位的楼层 //获取定位时间 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date date = new Date(amapLocation.getTime()); df.format(date); button.setText(city); mTvTitle.setText(city); aCache.put("city", city); Log.i(TAG,"----------" + city); } else { //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息 Log.e("AmapError", "location Error, ErrCode:" + amapLocation.getErrorCode() + ", errInfo:" + amapLocation.getErrorInfo()); } } } }; private void initViews() { aCache = ACache.get(this);//获取缓存 helper = new CityHelper(this, "city", null, 1);//初始化数据库 read = helper.getReadableDatabase();//拿到读取的read city_back = (ImageView) findViewById(R.id.city_back); city_commit = (TextView) findViewById(R.id.city_commit); mEtCityName = (EditTextWithDel) findViewById(R.id.et_search); sideBar = (SideBar) findViewById(R.id.sidrbar); dialog = (TextView) findViewById(R.id.dialog); mTvTitle = (TextView) findViewById(R.id.tv_title); sortListView = (ListView) findViewById(R.id.country_lvcountry); //填充控件 initDatas(); //填充省份数据 setAdapter(); } private void setAdapter() { //填充省份数据 SourceDateList = filledData(getDB()); Collections.sort(SourceDateList, new PinyinComparator()); sortListView.addHeaderView(initHeadView()); adapter = new SortAdapter(CityActivity.this, SourceDateList); sortListView.setAdapter(adapter);//填充listview //点击事件 initEvents(); } private void initEvents() { //设置右侧触摸监听 sideBar.setOnTouchingLetterChangedListener(new SideBar.OnTouchingLetterChangedListener() { @Override public void onTouchingLetterChanged(String s) { //该字母首次出现的位置 int position = adapter.getPositionForSection(s.charAt(0)); if (position != -1) { sortListView.setSelection(position + 1); } } }); //ListView的点击事件 sortListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { //因为头文件的存在(占用了一个栏位),所以选择的城市的下标(position)需要 -1 ; mTvTitle.setText(((CitySortModel) adapter.getItem(position - 1)).getName()); Toast.makeText(getApplication(), ((CitySortModel) adapter.getItem(position - 1)).getName(), Toast.LENGTH_SHORT).show(); aCache.put("city", ((CitySortModel) adapter.getItem(position - 1)).getName()); } }); //根据输入框输入值的改变来过滤搜索 mEtCityName.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { //当输入框里面的值为空,更新为原来的列表,否则为过滤数据列表 filterData(s.toString()); } @Override public void afterTextChanged(Editable s) { } }); city_back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); city_commit.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); } private void initDatas() { sideBar.setTextView(dialog); } //定位,热门城市 private View initHeadView() { View headView = getLayoutInflater().inflate(R.layout.headview, null); GridView mGvCity = (GridView) headView.findViewById(R.id.gv_hot_city); String[] datas = new String[]{"北京","上海","深圳","长沙","武汉","吉林"};//热门城市 //填充热门城市数据 final ArrayList<String> cityList = new ArrayList<>(); for (int i = 0; i < datas.length; i++) { cityList.add(datas[i]); } CityAdapter adapter = new CityAdapter(getApplicationContext(), R.layout.gridview_item, cityList); mGvCity.setAdapter(adapter); button = (Button) headView.findViewById(R.id.btn_city_name); //启动定位 mLocationClient.startLocation(); //点击定位操作 button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(CityActivity.this, "定位中....", Toast.LENGTH_SHORT).show(); //启动定位 mLocationClient.startLocation(); } }); return headView; } /** * 根据输入框中的值来过滤数据并更新ListView */ private void filterData(String filterStr) { List<CitySortModel> mSortList = new ArrayList<>(); if (TextUtils.isEmpty(filterStr)) { mSortList = SourceDateList; } else { mSortList.clear(); for (CitySortModel sortModel : SourceDateList) { String name = sortModel.getName(); if (name.toUpperCase().indexOf(filterStr.toString().toUpperCase()) != -1 || PinyinUtils.getPingYin(name).toUpperCase().startsWith(filterStr.toString().toUpperCase())) { mSortList.add(sortModel); } } } // 根据a-z进行排序 Collections.sort(mSortList, new PinyinComparator()); adapter.updateListView(mSortList); } //返回城市的名称的集合 private List<CitySortModel> filledData(List<CitySortModel> date) { List<CitySortModel> mSortList = new ArrayList<>(); ArrayList<String> indexString = new ArrayList<>(); for (int i = 0; i < date.size(); i++) { CitySortModel sortModel = new CitySortModel(); sortModel.setName(date.get(i).getName()); String pinyin = PinyinUtils.getPingYin(date.get(i).getName()); String sortString = pinyin.substring(0, 1).toUpperCase(); if (sortString.matches("[A-Z]")) { sortModel.setSortLetters(sortString.toUpperCase()); if (!indexString.contains(sortString)) { indexString.add(sortString); } } mSortList.add(sortModel); } Collections.sort(indexString); sideBar.setIndexText(indexString); return mSortList; } class SortAdapter extends BaseAdapter implements SectionIndexer { private List<CitySortModel> list = null; private Context mContext; public SortAdapter(Context mContext, List<CitySortModel> list) { this.mContext = mContext; this.list = list; } /** * 当ListView数据发生变化时,调用此方法来更新ListView */ public void updateListView(List<CitySortModel> list) { this.list = list; notifyDataSetChanged(); } public int getCount() { return this.list.size(); } public Object getItem(int position) { return list.get(position); } public long getItemId(int position) { return position; } public View getView(final int position, View view, ViewGroup arg2) { ViewHolder viewHolder = null; final CitySortModel mContent = list.get(position); if (view == null) { viewHolder = new ViewHolder(); view = LayoutInflater.from(mContext).inflate(R.layout.item_select_city, null); viewHolder.tvTitle = (TextView) view.findViewById(R.id.tv_city_name); viewHolder.tvLetter = (TextView) view.findViewById(R.id.tv_catagory); view.setTag(viewHolder); } else { viewHolder = (ViewHolder) view.getTag(); } int section = getSectionForPosition(position); if (position == getPositionForSection(section)) { viewHolder.tvLetter.setVisibility(View.VISIBLE); viewHolder.tvLetter.setText(mContent.getSortLetters()); } else { viewHolder.tvLetter.setVisibility(View.GONE); } viewHolder.tvTitle.setText(list.get(position).getName()); return view; } class ViewHolder { TextView tvLetter; TextView tvTitle; } public int getSectionForPosition(int position) { return list.get(position).getSortLetters().charAt(0); } public int getPositionForSection(int section) { for (int i = 0; i < getCount(); i++) { String sortStr = list.get(i).getSortLetters(); char firstChar = sortStr.toUpperCase().charAt(0); if (firstChar == section) { return i; } } return -1; } @Override public Object[] getSections() { return null; } } @Override protected void onPause() { super.onPause(); mLocationClient.stopLocation();//停止定位后,本地定位服务并不会被销毁 } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver);//取消广播注册 mLocationClient.onDestroy();//销毁定位客户端,同时销毁本地定位服务。 } //读取所有城市数据库 public List<CitySortModel> getDB() { final List<CitySortModel> list = new ArrayList<>(); Cursor cursor = read.rawQuery("select * from city order by _id asc", null);//查询所有城市 while (cursor.moveToNext()) { CitySortModel sortModel = new CitySortModel(); sortModel.setId(cursor.getString(cursor.getColumnIndex("_id"))); sortModel.setName(cursor.getString(cursor.getColumnIndex("name"))); list.add(sortModel); } return list; }}
主要代码就是这些,大部分都写有注释,应该不难理解,具体代码稍后会上传。
遇到的第二个问题就是SQLite操作的时候报了datebase is locked的问题,很常见的问题,
网上给的很多解决办法对于初学者来说都很难理解,有一个比较简单的办法,就是开启一个service服务,
在service里面进行SQLite的写入操作,读取数据库的时候最好是判断一下数据库是否是开启状态。
SQLite是一个轻量级的数据库,最多开启线程池不能超过两个。
遇到的第三问题就是在开启service服务的时候,写了startService(new Intent(this,MyService.class));
然而县城并没有开启,检查了很久才发现是忘了在Androidmanifest.xml文件里面注册service服务。
以上为今天遇到的问题的全部,如果有碰到同样问题的朋友,可以参考一下我的办法。
代码片段应该能解决定位中遇到的问题了(高德地图的集成请前往高德地图API官网自行查看),
具体的代码正在从项目中抽取。
第一次写博客,如有不成熟或者错误的地方,欢迎大家指出,如果有更好的想法,也期待您的无私分享。
demo下载地址
点击此处下载demo
- 安卓开发遇到的几个问题(网络定位,从网络获取所有省/市,SQLite,Service等)
- 安卓网络定位
- 安卓开发-定位的service
- 安卓从网络获取图片
- 安卓 新版本 获取wifi状态网络是否可用等
- 手机定位折腾记(1):安卓手机的网络定位与NetworkLocation.apk
- 安卓中的网络状态的获取
- 安卓获取网络视频的缩略图
- 获取一张网络图片(安卓)
- 关于网络的几个问题
- 安卓获取网络类型
- Android-Service(系统服务实例:定位,网络判断,电话服务 ,通知栏通知等)
- Android-Service(系统服务实例:定位,网络判断,电话服务 ,通知栏通知等)
- 仿CSDN安卓客户端(二)-----从网络上获取并解析html文件
- 安卓开发29:获取网络状态工具类
- 安卓开发中获取服务器网络延迟(ping)
- 安卓开发获取网络数据utile工具
- 对GPS、移动网络以及唯一标识码的属性获取--------------安卓开发第二步
- OpenCV中IplImage和单字节char*的相互转换
- Getting “org.hibernate.TransactionException: nested transactions not supported” error when deleting
- 《C++ Primer Plus(第六版)》(36)(第十六章 string类和标准模板库 编程练习和答案)
- Android网络——Http通信
- 奥塔在线:如何查看连接数?
- 安卓开发遇到的几个问题(网络定位,从网络获取所有省/市,SQLite,Service等)
- PowerMock相关
- Android录屏——屏幕录制命令screenrecord
- 【Android图像处理】图像处理之-油画效果
- 数据结构(十六) 线索二叉树讲解(带头节点后序加线索) 以及实现的完整代码
- idea 必备插件之键盘流篇
- Android Gson @SerializedName注解
- GIS就业参考系列之修炼篇——这里的黎明静悄悄
- [FUNC]RunOrActivate