Android 线程始终运行之我见

本文介绍了一个 Android 应用案例,该应用利用 WakeLock API 保持 CPU 在后台运行,确保 GPS 定位服务即使在手机休眠状态下也能正常工作。作者分享了一个具体的实现代码示例,并讨论了不同类型的 WakeLock 对 CPU 和屏幕的影响。

最近做Android手机GPS定位系统应用软件的开发,发现手机通过usb或屏幕亮的时候能够通过三种方式定位,一旦手机在休眠的时候,手机的cpu也休眠了,创建的线程会继续sleep,不会发生自己预期的效果,郁闷的事情困扰着自己,再闷也有解决的方案吧,加上蒸笼似的天气。

我的查阅了好许资料,也许自己的想法是正确的,什么都要靠事实说话,最好的解决方案就是在手机屏幕休眠时让cpu继续,才能让我理想的线程continue. 自己写了个demo,测试到凌晨一切正常。

public class GpsTest extends Activity {

/** Called when the activity is first created. */

private PowerManager.WakeLock myWakeLock;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

//启动一个线程

new Thread(new MyThread()).start();

PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);

myWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DoNotDimScreen");

//不让程序进入activity界面,直接跳转到手机界面

Intent intent = new Intent(Intent.ACTION_MAIN);

intent.addCategory(Intent.CATEGORY_HOME);

startActivity(intent);

}

@Override

protected void onPause() {

// TODO Auto-generated method stub

super.onPause();

boolean bo = myWakeLock.isHeld();

if (myWakeLock == null || ! bo) {

myWakeLock.acquire();

}

}

@Override

protected void onResume() {

// TODO Auto-generated method stub

super.onResume();

boolean bo = myWakeLock.isHeld();

if (myWakeLock == null || ! bo) {

myWakeLock.acquire();

}

}

private void print(String str) {

FileWriter fw = null;

BufferedWriter bw = null;

try {

SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd" + " "

+ "hh:mm:ss");

String datetime = tempDate.format(new java.util.Date()).toString();

String ss = "/sdcard/test.txt";

fw = new FileWriter(ss, true);//

// 创建FileWriter对象,用来写入字符流

bw = new BufferedWriter(fw); // 将缓冲对文件的输出

String myreadline = datetime + "[]" + str;

bw.write(myreadline + ""); // 写入文件

bw.newLine();

bw.flush(); // 刷新该流的缓冲

bw.close();

fw.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

try {

bw.close();

fw.close();

} catch (IOException e1) {

// TODO Auto-generated catch block

print("打印异常" + e1.toString());

}

}//

}

class MyThread implements Runnable {

@Override

public void run() {

// TODO Auto-generated method stub

while (true) {

try {

//print("进入线程");

Thread.sleep(30*1000);// 5 * 60 *

print("飞哥跑了一次 \n \n");

} catch (InterruptedException e) {

// TODO Auto-generated catch block

print("线程外部异常" + e.toString());

}

}

}

}

}

要加入权限才可以

<uses-permission android:name="android.permission.WAKE_LOCK" />

<uses-permission android:name="android.permission.DEVICE_POWER" />

API小资料

各种锁的类型对CPU 、屏幕、键盘的影响:

PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。

SCREEN_DIM_WAKE_LOCK:保持CPU 运转,允许保持屏幕显示但有可能是灰的,允许关闭键盘灯

SCREEN_BRIGHT_WAKE_LOCK:保持CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯

FULL_WAKE_LOCK:保持CPU 运转,保持屏幕高亮显示,键盘灯也保持亮度

ACQUIRE_CAUSES_WAKEUP:Normal wake locks don't actually turn on the illumination. Instead, they cause the illumination to remain on once it turns on (e.g. from user activity). This flag will force the screen and/or keyboard to turn on immediately, when the WakeLock is acquired. A typical use would be for notifications which are important for the user to see immediately.

ON_AFTER_RELEASE:f this flag is set, the user activity timer will be reset when the WakeLock is released, causing the illumination to remain on a bit longer. This can be used to reduce flicker if you are cycling between wake lock conditions.

从提供的引用来看,虽未直接提及Android线程运行窗口的介绍,但能从相关内容推导一些关联信息。 在Android中,窗口机制是重要的一部分。ViewRootImpl作为WindowManager与Window之间的中转站,管理整个Window。当Window中有请求发出时,会先由ViewRootImpl处理,再通过WindowManagerGlobal的Binder机制与WindowManagerService间接地进行通信 [^2]。 关于线程与窗口的关系,通常认为必须在主线程才可以更新UI,这是因为Android的UI更新不是线程安全的,如果在多个线程中同时更新UI可能会导致界面绘制混乱等问题。不过,也有提到“在子线程真的不能更新UI吗”,这暗示着在某些特殊情况下,可能存在在子线程更新UI的方法,但引用未详细说明 [^1][^2]。 从窗口机制整体来看,涉及到DecorView与SubDecor的创建加载、Window与Window Manager的创建加载、ViewRootImpl的创建以及视图真正加载等过程,这些过程与线程运行窗口可能存在联系。例如,在不同线程中创建和加载窗口组件时,可能会有不同的表现和限制。 ### 代码示例 以下是一个简单的示例,展示在主线程中更新UI(这里假设在Activity中): ```java import android.os.Bundle; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.textView); // 在主线程更新UI textView.setText("Hello, Android!"); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值