安卓保持CPU唤醒的方法



最近在做手机定位的事情,每次一锁屏,不过几分钟定位就停止了,无法继续定位。尝试了各种方法,最后使用高德地图的提示找到了解决方案。

总结我目前使用的方法如下:

1. 使用前台线程

2. 在jni中创建线程,实现数据收发(使用java创建线程应当一样的效果)

3. 收发使用TCP通信


最后使用高德的第三条提示实现后台持续定位。


高德地图的提示如下:http://lbs.amap.com/dev/ticket#/faq/277


1、通过创建Timer来保持CPU唤醒状态:

Android 的 Timer 类可以用来计划需要执行的任务。但 Timer 的问题是比较消耗手机电量(实现是用 WakeLock 让 CPU 保持唤醒状态);另外一点是:部分厂商将WakeLock也设置了休眠时间,就是说 Timer 很可能和CPU一起处于休眠状态。Timer 类只能解决一小部分问题。

2、通过AlarmManager保持CPU处于唤醒状态:

AlarmManager 是 Android 系统封装的用于管理 RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在 CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒 CPU。用 AlarmManager 来定时执行任务,CPU 可以正常的休眠,需要运行定位时醒来即可。但部分厂商为了使设备更加省电,将AlarmManager也做出了修改,例如5s一次的响应更改为50s或者是几分钟,有些干脆在CPU休眠后彻底停掉了。

3、通过心跳长链接保持client端CPU处于唤醒状态:

最佳唤醒CPU的方法是通过server端与client端的长链接通信。例如每次长链接保持5分钟时间,每30s通信一次,这样可以有效确保CPU处于唤醒状态。


具体代码如下:


//创建前台服务

public int onStartCommand(Intent intent, int flags, int startId) {
//super.onStartCommand(intent, flags, startId);


Intent notificationIntent = new Intent(this, MainActivity.class);
 
 PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
 Notification noti = new Notification.Builder(this)
       .setContentTitle("极光位置跟踪系统")
       .setContentText("正在跟踪您的位置")
       .setSmallIcon(R.drawable.ic_launcher)
       .setContentIntent(pendingIntent)
       .build();
 startForeground(ONGOING_NOTIFICATION, noti);
 
//创建gps监听器
CreateGpsListener(getApplicationContext());


//jni中的线程函数

static void* TestMain(void* srvname) {


int index = 0;
char  msg[128];


int udpSockfd;
struct sockaddr_in address;//处理网络通信的地址
int sockfd;
int err;


//memset(&address,0,sizeof(address));
address.sin_family=AF_INET;
address.sin_addr.s_addr=inet_addr("192.168.2.101");//这里不一样
address.sin_port=htons(1206);
udpSockfd = socket(AF_INET,SOCK_DGRAM,0);//IPV4  SOCK_DGRAM 数据报套接字(UDP协议)


while(1)
{
index ++;


if(sockfd  != -1)
{
sprintf(msg,"thread running %d\n",index);


if(send(sockfd,msg,strlen(msg),0) == strlen(msg))
{
if(recv(sockfd,msg,sizeof(msg)-1,0) <= 0)
{
close(sockfd);
sockfd = -1;
}
}
else
{
const char *rsp = "tcp send error\n";
sendto(udpSockfd,rsp,strlen(rsp),0,(struct sockaddr *)&address,sizeof(address));
close(sockfd);
sockfd = -1;
}


if((index % 100) == 0)
{
close(sockfd);
sockfd = -1;
}
}
else
{
const char *rsp = "connect server 192.168.2.101\n";
sendto(udpSockfd,rsp,strlen(rsp),0,(struct sockaddr *)&address,sizeof(address));


sockfd=socket(AF_INET,SOCK_STREAM,0);
if(sockfd==-1)
{
break;
}


struct sockaddr_in addr_ser;
addr_ser.sin_family=AF_INET;
addr_ser.sin_addr.s_addr=inet_addr("192.168.2.101");
addr_ser.sin_port=htons(1124);
err=connect(sockfd,(struct sockaddr *)&addr_ser,sizeof(addr_ser));
if(err==-1)
{
close(sockfd);
sockfd = -1;
}
}


sprintf(msg,"udp thread running %d\n",index);
//sendto(udpSockfd,msg,strlen(msg),0,(struct sockaddr *)&address,sizeof(address));
}


return NULL;
}


//定位的gps数据也是通过tcp发送的。

//收到定位信息
@Override
public void onReceiveLocation(BDLocation location) 
{
m_centerPos = new LatLng(location.getLatitude(),location.getLongitude());
m_setPosNum ++;

(new Thread(){
@Override
public void run() {
String strLocation = "   "+m_setPosNum + ":location gps :" + m_centerPos.latitude + "," + m_centerPos.longitude + "\n";

SendData(strLocation.getBytes(), strLocation.length(),m_destIp,m_destPort);
}
}).start();
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值