一学期的课程设计又开始了,虽然以后不搞安卓,但是课设还是想好好完成的,因为之前做过地图开发,所以选了一个跟

这个相关的题目,其实有一个校车系统也可以选,但是之前做过一个相似度接近80%的东西,不想混混过关,就算了,这是题目

实现思路并不难,孩子端启动一个后台服务,每隔3分钟向后台服务器发送一次位置信息,后端保存,家长端通过时间段来获得孩子位置,实际上就是根据时间戳

来了,然后标注在家长端地图上,至于打电话什么的,调系统API就可以,从星期二到今天,将孩子端完成,后端完成,父亲端也差不多了,现在还有一个

难点就是最后的要求15分钟没有信息汇报就需要警告,还没搞清楚怎么实现...明天要考六级,今天得知软考挂了伤心死了,就差那么几分啊,要

是没看错最后的那个大题就过了

整个课设的技术包括:前端:安卓,七牛云SDK,Volley网络框架,百度地图SDK

后台:SpringBoot+Mybatis+mysql

现在记录一下每个三分钟发布一次信息的实现和上传头像的实现(之前还没弄过安卓上传文件所以想试试)

都知道安卓四大组件,其中service就是一个重要的东西,这里我说的是非绑定的service,它是不停的运行的,所以我们可以利用它来给我们的应用添加一些有趣的功能

比如我们退出软件仍旧下载东西就是用这个实现的,但是对于本题来讲,光是有服务是行不通的,我们还需要一个定时器,而且,还需要是稳定的,而不是那种退出APP就

停止的,综合考虑,当然是用AlarmManager了,他是安卓的系统服务,所以不会随着应用退出而停止,闹钟就是用这个来实现的.,AlarmManager如果参照网上的一些demo

基本都会遇到坑,因为谷歌官方更新了这个,用错了会有很大误差,这里推荐看一下这个博客:我也是看了他的

https://www.cnblogs.com/leipDao/p/8203684.html

从这个博客里了解到AlarmManager在安卓高版本里会有误差,但还好谷歌有新的API来对付误差,但定时的功能就不好实现了,那么这里采用的办法就是在调用一次之后在重新

发送,就达到了计时的目的

首先是一个工具类,负责实例化AlarmManager对象,唤醒闹钟

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log; import software.com.safelocatechild.BroadcastReceiver.LocateInfoReceiver; /**
* Created by 31786 on 2018/12/11.
* 计时器,用于隔断时间发送自己的位置
*/
public class AlarmManagerUtils { private static final long TIME_INTERVAL = 15 * 1000;//闹钟执行任务的时间间隔
private Context context;
public static AlarmManager am;
public static PendingIntent pendingIntent; private AlarmManagerUtils(Context aContext) {
this.context = aContext;
} private static AlarmManagerUtils instance = null; public static AlarmManagerUtils getInstance(Context aContext) {
if (instance == null) {
synchronized (AlarmManagerUtils.class) {
if (instance == null) {
Log.d("Alarm","实例化");
instance = new AlarmManagerUtils(aContext);
}
}
}
return instance;
} public void createGetUpAlarmManager() {
Log.d("Alarm","创建");
am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, LocateInfoReceiver.class);
intent.putExtra("msg", "测试");
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);//每隔5秒发送一次广播
} @SuppressLint("NewApi")
public void getUpAlarmManagerStartWork() {
//版本适配
Log.d("Alarm","开始工作");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0及以上
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {// 4.4及以上
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
pendingIntent);
} else {
am.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), TIME_INTERVAL, pendingIntent);
}
} @SuppressLint("NewApi")
public void getUpAlarmManagerWorkOnReceiver() {
//高版本重复设置闹钟达到低版本中setRepeating相同效果
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 6.0及以上
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + TIME_INTERVAL, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {// 4.4及以上
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ TIME_INTERVAL, pendingIntent);
}
}
}

  

在这时候,就是在服务里启动它,并且在一次计时过后重新开启一次计时,从而达到不断计时的目的

下面是个服务,负责发送广播,好像这样不太好,但我对这个不熟,先这样再说吧...

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log; import software.com.safelocatechild.activity.Welcome;
import software.com.safelocatechild.util.AlarmManagerUtils; public class LocateService extends Service {
public LocateService() {
} @Override
public void onCreate(){
Log.d("-------","服务创建");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent,int flagId,int startId){
Log.d("-------","服务运行");
// onStartCommand(intent,flagId,startId);
testAlarm();
return super.onStartCommand(intent,flagId,startId);
}
@Override
public void onDestroy(){
//发送结束信息,告知parent
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
public void testAlarm(){
AlarmManagerUtils alarmManagerUtils = AlarmManagerUtils.getInstance(getApplicationContext());
alarmManagerUtils.createGetUpAlarmManager();
alarmManagerUtils.getUpAlarmManagerStartWork();
}
}

  

广播接收:

package software.com.safelocatechild.BroadcastReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast; import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.mapapi.map.BaiduMap; import org.json.JSONException;
import org.json.JSONObject; import java.util.HashMap;
import java.util.Map; import software.com.safelocatechild.R;
import software.com.safelocatechild.activity.Child;
import software.com.safelocatechild.activity.Login;
import software.com.safelocatechild.listener.LocationListener;
import software.com.safelocatechild.util.AlarmManagerUtils;
import software.com.safelocatechild.util.Const; public class LocateInfoReceiver extends BroadcastReceiver { @Override
public void onReceive(final Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
String extra = intent.getStringExtra("msg");
Log.d("---------------", "extra = " + extra);
Log.d("-------","接收到了");
LocationClient client = new LocationClient(context);
client.registerLocationListener(new LocationListener(){
/*
* 通过GPS定位起点
* */
@Override
public void onReceiveLocation(BDLocation location){
System.out.print("LocationClient----");
if (location!=null){
//定时发送经纬度,写接口
String childid = Const.context.getSharedPreferences("Setting",Context.MODE_MULTI_PROCESS).
getString("childid","");
Log.d("childid = ",childid);
Log.d("Send longitude",location.getLongitude()+"");
Toast.makeText(Const.context,childid+location.getLongitude()+"-"+location.getLatitude(),Toast.LENGTH_SHORT).show();
//Log.d("Send latitude",location.getLatitude()+"");
sendLocation(childid,location.getLatitude(),location.getLongitude());
//再次启动闹钟
AlarmManagerUtils.getInstance(context).getUpAlarmManagerWorkOnReceiver();
}else {
Log.d("location = ","null");
} }
});
client.start(); }
//发送位置
public boolean sendLocation(final String childid,final Double latitude, final Double longitude){
//请求地址,需要换接口
String url = Const.context.getResources().getString(R.string.insertLocation);
String tag = "Login";
//取得请求队列
RequestQueue requestQueue = Volley.newRequestQueue(Const.context);
//防止重复请求,所以先取消tag标识的请求队列
requestQueue.cancelAll(tag);
//创建StringRequest,定义字符串请求的请求方式为POST(省略第一个参数会默认为GET方式)
StringRequest request = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
if(jsonObject.getBoolean("canInsert")){
//等待接口
Log.d("发送位置成功"," ");
}else{
Log.d("发送位置失败"," ");
}
} catch (JSONException e) {
//做自己的请求异常操作,如Toast提示(“无网络连接”等)
Log.d("LocateInfoReceiver","JsonException");
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//做自己的响应错误操作,如Toast提示(“请稍后重试”等)
Log.d("LocateInfoReceiver","VolleyError");
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("childid",childid);
params.put("longitude",String.valueOf(longitude)); //注⑥
params.put("latitude",String.valueOf(latitude));
params.put("time",System.currentTimeMillis()+"");
Log.d("位置发送时间",System.currentTimeMillis()+"");
return params;
} }; //设置Tag标签
request.setTag(tag);
request.setRetryPolicy(new DefaultRetryPolicy(20*1000,1,1.0f));
//将请求添加到队列中
requestQueue.add(request);
return true;
}
}

  

好了,从数据库里的结果来看,效果还行,但因为中途有时间损耗,肯定还是有一点影响的

之后再说上传图片,七牛云的使用就不多说了,官方有文档,我的做法是用TakePhoto框架得到图片,然后将图片化成能上传的格式

TakePhoto的使用我之前的博客里有讲:https://www.cnblogs.com/Yintianhao/p/9327191.html

重点的三个函数:一个上传,也就是里面有七牛云的上传和回调,还有一个将Bitmap图片转为byte数组,另一个就是获得一个随机名字

名字直接关系到取图片的链接,同时在我这个题目中也是存在用户信息表里面的

//上传图片
public void uploadImage(final Bitmap bitmap, String fileName) {
//定义数据上传结束后的处理动作
final UpCompletionHandler upCompletionHandler = new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
headSculpture.setImageBitmap(bitmap);
}
};
final UploadOptions uploadOptions = new UploadOptions(null, null, false, new UpProgressHandler() {
@Override
public void progress(String key, final double percent) {
//百分数格式化
NumberFormat fmt = NumberFormat.getPercentInstance();
fmt.setMaximumFractionDigits(2);//最多两位百分小数,如25.23%
}
}, new UpCancellationSignal() {
@Override
public boolean isCancelled() {
return false;
}
});
try {
//上传图片
QiNiuInitialize.getSingleton().put(getByte(bitmap), fileName, getUpToken(), upCompletionHandler, uploadOptions);
} catch (Exception e) {
e.printStackTrace();
}
} //通过UUID获得一个随机的文件名
public String getRandomName(){
String randomName = UUID.randomUUID().toString().replaceAll("-","")+".jpeg";
return randomName;
} //获取图片的byte数组
public byte[] getByte(Bitmap bm) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 80, baos);
return baos.toByteArray();
}

  

好了,上传到这里,那么我们如何根据图片的链接来获取图片并显示在控件里呢,看这里:

 //根据URL获取图片,path即url
public Bitmap getBitmap(String path) throws IOException {
//严格模式否则会出错,具体作用可以查
StrictMode.setThreadPolicy(new
StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(
new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects().detectLeakedClosableObjects().penaltyLog().penaltyDeath().build());
Log.d("path","="+path);
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if (conn.getResponseCode() == 200) {
InputStream inputStream = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
return bitmap;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}

 

好了,先写到这了,听听听力准备明天的六级去了!!

AlarmManager的使用和七牛云android SDK上传图片的更多相关文章

  1. PHP 下载七牛云的sdk

    1,语法 composer require qiniu/php-sdk 2,出现以下图片内容就是下载七牛云的sdk成功

  2. 在ThinkPHP框架(5.0.24)下引入Ueditor并实现向七牛云对象存储上传图片同时将图片信息保存到MySQL数据库,同时实现lazyload懒加载

    这是我花了很多天的时间才得以真正实现的一组需求. 文章后面有完整Demo的GitHub链接. 一. 需求描述 1. 应用是基于ThinkPHP5开发的: 2. 服务器环境是LNMP,PHP版本是7.2 ...

  3. 七牛云 PHP SDK服务器鉴权失败!参数解释

    昨天搞了一下午,用7牛官方的SDK demo 1.上传凭证 $policy = array( 'callbackUrl' => 'http://api.example.com/qiniu/upl ...

  4. BAE Flask UEditor 使用七牛云

    1. 配置BAE支持七牛云的SDK BAE的python requirements当然不支持竞争对手了. 解决方法: 把qiniu这个文件包直接放置在你项目的目录中(与其他app同级) 运行会发现缺少 ...

  5. Python实现七牛云视频播放

    这篇文章是使用Python的Web框架Django Rest Framework来提供视频相关的api接口,主要功能包括视频上传.视频转码.视频访问授权.删除视频文件.视频截图功能. 七牛云上的基本概 ...

  6. SpringSpringBoot上传文件到七牛云

    准备工作 maven pom.xml添加七牛云的sdk依赖 <dependency> <groupId>com.qiniu</groupId> <artifa ...

  7. php利用七牛云的对象存储完成图片上传-高效管理图片

    在搭建个人博客时,大家都会买一台云服务器.可是图片的存放一直是一个问题,冷月帮大家找到一个免费的第三方平台对象存储-七牛云.大家可以把图片上传到七牛云的对象存储,大大节约服务器的压力. 首先,大家在使 ...

  8. Android开发中使用七牛云存储进行图片上传下载

    Android开发中的图片存储本来就是比较耗时耗地的事情,而使用第三方的七牛云,便可以很好的解决这些后顾之忧,最近我也是在学习七牛的SDK,将使用过程在这记录下来,方便以后使用. 先说一下七牛云的存储 ...

  9. 七牛云存储Python SDK使用教程 - 上传策略详解

    文 七牛云存储Python SDK使用教程 - 上传策略详解 七牛云存储 python-sdk 七牛云存储教程 jemygraw 2015年01月04日发布 推荐 1 推荐 收藏 2 收藏,2.7k  ...

随机推荐

  1. Log4J2用法

    一.    关于Log4J 2015年5月,Apache宣布Log4J 1.x 停止更新.最新版为1.2.17. 如今,Log4J 2.x已更新至2.7. 官方网址:http://logging.ap ...

  2. scrapy+redis去重实现增量抓取

    class ProjectnameDownloaderMiddleware(object): # Not all methods need to be defined. If a method is ...

  3. 169. Majority Element (Array)

    Given an array of size n, find the majority element. The majority element is the element that appear ...

  4. 35 【kubernetes】configMap

    kubernetes可以驱动容器的运行,并且把容器的运行放置在kubernetes定义的体系结构中pods这一级. 但是容器运行通常会需要某些参数,比如环境变量或者硬件使用情况. 为了解决对每个con ...

  5. JavaScript onclick传递对象参数(easyui传递一行数据时)错误:uncaught SyntaxError: Unexpected identifier

    JavaScript onclick传递对象参数(easyui传递一行数据时)错误:uncaught SyntaxError: Unexpected identifier 博主遇到的是用onclick ...

  6. linux用户和组管理,/etc/passwd 、/etc/shadow和/etc/group --学习

    一./etc/passwd 和/etc/shadow解释 与用户相关的系统配置文件主要有/etc/passwd 和/etc/shadow,其中/etc/shadow是用户资讯的加密文件,比如用户的密码 ...

  7. Object强转为实体类类型失败!!!!!!

    这是从我CSDN博客直接拿来的图片废话不多说,直接上代码:

  8. 4412 uboot启动分析

    感谢sea1105, https://blog.csdn.net/sea1105/article/details/52142772 在学习过程中,由于tiny4412资料太过于少,因此参考210的视屏 ...

  9. 最短路径(SP)问题相关算法与模板

    相关概念: 有向图.无向图:有向图的边是双行道,无向图的边是单行道.在处理无向图时,可以把一条无向边看做方向相反的两条有向边. 圈 cycle / 回路 circuit:在相同顶点上开始并结束且长度大 ...

  10. 面试简单整理之JVM

    194.说一下 jvm 的主要组成部分?及其作用? JVM内存分为“堆”.“栈”和“方法区”三个区域,分别用于存储不同的数据. 堆内存用于存储使用new关键字所创建的对象: 栈内存用于存储程序运行时在 ...