团队冲刺第二天
1、这次在昨天的定位代码上进行了优化了修改。
修复了之前在定位上面的bug。现在满足的定位条件有如下相关的情况:可以实现热力图定位。普通的定位。以及卫星定位
之后里面包含复位、停止定位、开始定位、等选项。里面具体的功能已经实现了。
这次遇到的麻烦是:有些权限不能默认进行设置。需要用户手动进行添加。造成麻烦。
然后明天准备完成的工作是修改相应的权限获取。由于明天课程比较多。如果还有时间,将进行学习运动轨迹的记录问题
下面是这次完成的相应的代码以及运行的结果图:
package com.example.dingwei; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.SDKInitializer; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapStatus; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.model.LatLng; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private MapView mMapView; private BaiduMap mBaiduMap; public LocationClient mLocationClient; public BDLocationListener myListener = new MyLocationListener(); private Button bt; private Button button; private Button buttons; private Button buttonsunder; private Button buttonsunder2; private LatLng latLng; private boolean isFirstLoc = true; // 是否首次定位 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //在使用SDK各组件之前初始化context信息,传入ApplicationContext //注意该方法要再setContentView方法之前实现 SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); initView(); initMap(); } private void initMap() { //获取地图控件引用 mBaiduMap = mMapView.getMap(); //普通地图 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); mBaiduMap.setMyLocationEnabled(true); //默认显示普通地图 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); //开启交通图 mBaiduMap.setTrafficEnabled(true); //开启热力图 mBaiduMap.setBaiduHeatMapEnabled(true); // 开启定位图层 mBaiduMap.setMyLocationEnabled(true); mLocationClient = new LocationClient(getApplicationContext()); //声明LocationClient类 //配置定位SDK参数 initLocation(); mLocationClient.registerLocationListener(myListener); //注册监听函数 //开启定位 mLocationClient.start(); //图片点击事件,回到定位点 mLocationClient.requestLocation(); } //配置定位SDK参数 private void initLocation() { LocationClientOption option = new LocationClientOption(); option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy );//可选,默认高精度,设置定位模式,高精度,低功耗,仅设备 option.setCoorType("bd09ll");//可选,默认gcj02,设置返回的定位结果坐标系 int span = 1000; option.setScanSpan(span);//可选,默认0,即仅定位一次,设置发起定位请求的间隔需要大于等于1000ms才是有效的 option.setIsNeedAddress(true);//可选,设置是否需要地址信息,默认不需要 option.setOpenGps(true);//可选,默认false,设置是否使用gps option.setLocationNotify(true);//可选,默认false,设置是否当GPS有效时按照1S/1次频率输出GPS结果 option.setIsNeedLocationDescribe(true);//可选,默认false,设置是否需要位置语义化结果,可以在BDLocation // .getLocationDescribe里得到,结果类似于“在北京天安门附近” option.setIsNeedLocationPoiList(true);//可选,默认false,设置是否需要POI结果,可以在BDLocation.getPoiList里得到 option.setIgnoreKillProcess(false); option.setOpenGps(true); // 打开gps //可选,默认true,定位SDK内部是一个SERVICE,并放到了独立进程,设置是否在stop的时候杀死这个进程,默认不杀死 option.SetIgnoreCacheException(false);//可选,默认false,设置是否收集CRASH信息,默认收集 option.setEnableSimulateGps(false);//可选,默认false,设置是否需要过滤GPS仿真结果,默认需要 mLocationClient.setLocOption(option); } //实现BDLocationListener接口,BDLocationListener为结果监听接口,异步获取定位结果 public class MyLocationListener implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { latLng = new LatLng(location.getLatitude(), location.getLongitude()); // 构造定位数据 MyLocationData locData = new MyLocationData.Builder() .accuracy(location.getRadius()) // 此处设置开发者获取到的方向信息,顺时针0-360 .direction(100).latitude(location.getLatitude()) .longitude(location.getLongitude()).build(); // 设置定位数据 mBaiduMap.setMyLocationData(locData); // 当不需要定位图层时关闭定位图层 //mBaiduMap.setMyLocationEnabled(false); if (isFirstLoc) { isFirstLoc = false; LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); MapStatus.Builder builder = new MapStatus.Builder(); builder.target(ll).zoom(18.0f); mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build())); if (location.getLocType() == BDLocation.TypeGpsLocation) { // GPS定位结果 Toast.makeText(MainActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show(); } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) { // 网络定位结果 Toast.makeText(MainActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show(); } else if (location.getLocType() == BDLocation.TypeOffLineLocation) { // 离线定位结果 Toast.makeText(MainActivity.this, location.getAddrStr(), Toast.LENGTH_SHORT).show(); } else if (location.getLocType() == BDLocation.TypeServerError) { Toast.makeText(MainActivity.this, "服务器错误,请检查", Toast.LENGTH_SHORT).show(); } else if (location.getLocType() == BDLocation.TypeNetWorkException) { Toast.makeText(MainActivity.this, "网络错误,请检查", Toast.LENGTH_SHORT).show(); } else if (location.getLocType() == BDLocation.TypeCriteriaException) { Toast.makeText(MainActivity.this, "手机模式错误,请检查是否飞行", Toast.LENGTH_SHORT).show(); } } } } private void initView() { mMapView = (MapView) findViewById(R.id.bmapView); bt = (Button) findViewById(R.id.bt); bt.setOnClickListener(this); button = (Button) findViewById(R.id.button); button.setOnClickListener(this); buttons = (Button) findViewById(R.id.buttons); buttons.setOnClickListener(this); buttonsunder=(Button) findViewById(R.id.butttonunder); buttonsunder.setOnClickListener(this); buttonsunder2=(Button) findViewById(R.id.butttonunder2); buttonsunder2.setOnClickListener(this); } @Override protected void onDestroy() { super.onDestroy(); //在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理 mMapView.onDestroy(); } @Override protected void onResume() { super.onResume(); //在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理 mMapView.onResume(); } @Override protected void onPause() { super.onPause(); //在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理 mMapView.onPause(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt: //把定位点再次显现出来 MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng); mBaiduMap.animateMapStatus(mapStatusUpdate); isFirstLoc=true; break; case R.id.button: //卫星地图 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE); isFirstLoc=true; break; case R.id.buttons: //普通地图 mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL); isFirstLoc=true; break; case R.id.butttonunder: //停止定位 mBaiduMap.setMyLocationEnabled(false); break; case R.id.butttonunder2: //开始定位 mBaiduMap.setMyLocationEnabled(true); MapStatusUpdate mapStatusUpdate1 = MapStatusUpdateFactory.newLatLng(latLng); mBaiduMap.animateMapStatus(mapStatusUpdate1); isFirstLoc=true; break; } } }

2、今天完成了注册的相关功能,实现了账号验证,设置头像,(拍照和直接设置本地图片),遇到的问题是在虚拟机上打开相机没问题,但是在真机运行打开相机就会闪退,最后通过在网上查阅相关资料解决,下面是主要代码,明天要完成的是登录相关
package com.register; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.StrictMode; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.Toast; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import com.login.LoginActivity; import com.example.keeprunning1.R; import com.user.User; import com.user.UserOperator; import java.io.File; import java.util.List; public class RegisterActivity extends AppCompatActivity implements View.OnClickListener { //注册信息 private ImageButton ibNavigationBack; private EditText etRegisterUsername; private EditText etRegisterPwdInput; private EditText etRegisterPwdsInput; private Button btRegisterSubmit; //头像 private Button chooseFromAlbum; private ImageView userPicture; protected static final int CHOOSE_PICTURE = 0; protected static final int TAKE_PICTURE = 1; private static final int CROP_SMALL_PICTURE = 2; protected static Uri tempUri; private String userpicture = ""; //提交,验证 private List<User> userList; private UserOperator muserOperator; private int wxat; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.register); muserOperator=new UserOperator(this); init(); //取消严格模式 FileProvider if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder(); StrictMode.setVmPolicy( builder.build() ); } } private void init() { ibNavigationBack = (ImageButton) findViewById(R.id.ib_navigation_back); userPicture = (ImageView) findViewById(R.id.user_picture); chooseFromAlbum = (Button) findViewById(R.id.choose_from_album); etRegisterUsername = (EditText) findViewById(R.id.et_register_username); etRegisterPwdInput = (EditText) findViewById(R.id.et_register_pwd_input); etRegisterPwdsInput = (EditText) findViewById(R.id.et_register_pwds_input); btRegisterSubmit = (Button) findViewById(R.id.bt_register_submit); //按钮点击事件,返回登录界面,头像选择,确定注册 ibNavigationBack.setOnClickListener(this); chooseFromAlbum.setOnClickListener(this); btRegisterSubmit.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.ib_navigation_back: Intent intent = new Intent(this, LoginActivity.class); startActivity(intent); finish(); break; case R.id.choose_from_album: chosePicture(); break; case R.id.bt_register_submit: String username = etRegisterUsername.getText().toString().trim(); String psw = etRegisterPwdInput.getText().toString().trim(); String psw1 = etRegisterPwdsInput.getText().toString().trim(); if (!psw.equals(psw1)) { Toast.makeText(this, "两次密码不一致", Toast.LENGTH_SHORT).show(); } //判断不为空且不是空串 else if (TextUtils.isEmpty(username) || TextUtils.isEmpty(psw) || TextUtils.isEmpty(psw1)) { Toast.makeText(this, "存请将信息填写完整", Toast.LENGTH_SHORT).show(); } else { User bean = muserOperator.isExit(username); if (bean!= null) { Toast.makeText(this, "该用户已存在,请重新注册", Toast.LENGTH_SHORT).show(); } else { User beans = new User(username, psw, userpicture, "0"); muserOperator.addUser(beans); Intent intent2 = new Intent(this, LoginActivity.class); Bundle bundle=new Bundle(); bundle.putString("username",username); bundle.putString("password",psw); intent2.putExtras(bundle); setResult(0x11,intent2); finish(); Toast.makeText(this, "注册成功", Toast.LENGTH_SHORT).show(); } } break; } } /* 修改头像对话框 */ public void chosePicture() { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("设置头像"); String[] items = {"选择本地照片", "拍照"}; builder.setNegativeButton("取消", null); builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case CHOOSE_PICTURE://从本地选择 Intent openAlbumIntent = new Intent( Intent.ACTION_GET_CONTENT); openAlbumIntent.setType("image/"); startActivityForResult(openAlbumIntent, CHOOSE_PICTURE); break; case TAKE_PICTURE: // 拍照 Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); tempUri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "image.jpg")); // 指定照片保存路径(SD卡),image.jpg为一个临时文件,每次拍照后这个图片都会被替换 openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri); startActivityForResult(openCameraIntent, TAKE_PICTURE); break; } } }); builder.create().show(); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { // 如果返回码是可以用的 switch (requestCode) { case TAKE_PICTURE: startPhotoZoom(tempUri); // 开始对图片进行裁剪处理 break; case CHOOSE_PICTURE: startPhotoZoom(data.getData()); // 开始对图片进行裁剪处理 break; case CROP_SMALL_PICTURE: if (data != null) { setImageToView(data); // 让刚才选择裁剪得到的图片显示在界面上 } break; } } } /** * 裁剪图片方法实现 * * @param uri */ protected void startPhotoZoom(Uri uri) { if (uri == null) { Log.i("tag", "The uri is not exist."); } tempUri = uri; Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); // 设置裁剪 intent.putExtra("crop", "true"); // aspectX aspectY 是宽高的比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); // outputX outputY 是裁剪图片宽高 intent.putExtra("outputX", 150); intent.putExtra("outputY", 150); intent.putExtra("return-data", true); startActivityForResult(intent, CROP_SMALL_PICTURE); } /** * 保存裁剪之后的图片数据 * @param * @param data */ protected void setImageToView(Intent data) { Bundle extras = data.getExtras(); if (extras != null) { Bitmap photo = extras.getParcelable("data"); photo = Utils.toRoundBitmap(photo, tempUri); // 这个时候的图片已经被处理成圆形的了 userPicture.setImageBitmap(photo); uploadPic(photo); } } private void uploadPic(Bitmap bitmap) { // 上传至服务器 // ... 可以在这里把Bitmap转换成file,然后得到file的url,做文件上传操作 // 注意这里得到的图片已经是圆形图片了 // bitmap是没有做圆形处理的,但已经被裁剪了 String imagePath = Utils.savePhoto(bitmap, Environment .getExternalStorageDirectory().getAbsolutePath(), String .valueOf(System.currentTimeMillis())); Log.e("imagePath", imagePath + ""); String m = "666"; Log.d("volley", m); if (imagePath != null) { // 拿着imagePath上传了 userpicture=imagePath; } } }


3.我在昨天的基础上学习了多音乐的播放,切换音乐,进度条显示。设置按钮上一首和下一首的操作,发现用到了线程方面的知识,我又重新学习了线程。并打算通过SD可以直接使用手机内存中的音乐,但是一直显示SD音乐导入不进去。明天继续bug的修改。
主要代码:
package com.example.keeprunning; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Environment; import android.util.Log; import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.List; public class MusicService { //获取SD卡总目录 //private static final File PATH = Environment.getExternalStorageDirectory(); String PATH=Environment.getExternalStorageDirectory().getAbsolutePath(); //存放找到的所有mp3的绝对路径 public List<String> musicList; //定义多媒体对象 public MediaPlayer player; //当前播放的歌曲在List中的下标,flag为标致 public int songNum; //当前播放的歌曲名 public String songName; //写一个内部类供加载mp3文件的时候调用 class MusicFilter implements FilenameFilter { public boolean accept(File dir, String name) { //返回当前目录所有以.mp3结尾的文件 return (name.endsWith(".mp3")); } } //在MusicService类的无参构造函数中实例化对象,并把这些MP3文件放到musicList中 public MusicService() { super(); //实例化一个多媒体对象 player = new MediaPlayer(); //实例化一个List链表数组 musicList = new ArrayList<String>(); try { //获取根目录的二级目录Music File MUSIC_PATH = new File(PATH, "Music"); if (MUSIC_PATH.listFiles(new MusicFilter()).length > 0) { for (File file : MUSIC_PATH.listFiles(new MusicFilter())) { musicList.add(file.getAbsolutePath()); } } } catch (Exception e) { Log.i("TAG", "读取文件异常"); } } //用setPlayName方法来修改获取到的mp3文件的名字供我们在TextView页面中使用 public void setPlayName(String dataSource){ File file=new File(dataSource); String name=file.getName(); int index=name.lastIndexOf("."); songName=name.substring(0,index); } //定义play类实现单首音乐的播放 public void play(){ try{ //重制多媒体 player.reset(); //得到当前播放音乐的路径 String dataSource =musicList.get(songNum); //载取歌名 setPlayName(dataSource); //指定参数为音频文件 player.setAudioStreamType(AudioManager.STREAM_MUSIC); //为多媒体对象设置播放路径 player.setDataSource(dataSource); //准备播放 player.prepare(); //开始播放 player.start(); //setOnCompletionListener当前多媒体对象播放完成时发生的事件 player.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ public void onCompletion(MediaPlayer arg0){ //如果当前歌曲播放完毕,自动播放下一首 next(); } }); }catch(Exception e){ Log.v("MusicService", e.getMessage()); } } //继续播放 public void goPlay(){ int position=getCurrentProgress(); //设置当前MediaPlayer的播放位置,单位是毫秒 player.seekTo(position); try{ //同步方式装载流媒体文件 player.prepare(); }catch(Exception e){ e.printStackTrace(); } player.start(); } // 获取当前进度 public int getCurrentProgress() { if (player != null & player.isPlaying()) { return player.getCurrentPosition(); } else if (player != null & (!player.isPlaying())) { return player.getCurrentPosition(); } return 0; } public void next() { songNum = songNum == musicList.size() - 1 ? 0 : songNum + 1; play(); } public void last() { songNum = songNum == 0 ? musicList.size() - 1 : songNum - 1; play(); } // 暂停播放 public void pause() { if (player != null && player.isPlaying()){ player.pause(); } } public void stop() { if (player != null && player.isPlaying()) { player.stop(); player.reset(); } } }
//设置当前播放的信息 private String setPlayInfo(int position,int max){ String info="正在播放:"+musicService.songName+"\t\t"; int pMinutes=0; while(position>=60){ pMinutes++; position-=60; } String now=(pMinutes<10?"0"+pMinutes:pMinutes)+":"+(position<10?"0"+position:position); int mMinutes=0; while(max>=60){ mMinutes++; max-=60; } String all=(mMinutes<10?"0"+mMinutes:mMinutes)+":"+(max<10?"0"+max:max); return info+now+"/"+all; } //填充获取到的文件名字 //向列表中添加mp3名字 private void setListViewAdapter() { String[] str = new String[musicService.musicList.size()]; int i = 0; for (String path : musicService.musicList) { File file = new File(path); str[i++] = file.getName(); } ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, str); listView = (ListView) findViewById(R.id.lv1); listView.setAdapter(adapter); } public void run(){ int position, mMax, sMax; while (!Thread.currentThread().isInterrupted()) if (musicService.player != null && musicService.player.isPlaying()) { //得到当前歌曲播放进度(秒) position = musicService.getCurrentProgress(); //最大秒数 mMax = musicService.player.getDuration(); //seekBar最大值,算百分比 sMax = seekBar.getMax(); //获取一个Message Message m = handler.obtainMessage(); //seekBar进度条的百分比 m.arg1 = position * sMax / mMax; m.arg2 = position; m.what = UPDATE; handler.sendMessage(m); // handler.sendEmptyMessage(UPDATE); try { // 每间隔1秒发送一次更新消息 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } }