文章目录

  • 1、Android服务
    • 1.1、定义
    • 1.2、基本用法
      • 1.2.1、定义一个服务
      • 1.2.2、服务注册
      • 1.2.3、启动和停止服务
      • 1.2.4、活动和服务进行通信
    • 1.3、带绑定的服务示例
      • 1.3.1、定义服务类
      • 1.3.2、客户端(Activity)绑定与交互​
      • 1.3.3、AndroidManifest.xml 注册​
      • 1.3.4、关键点
  • 2、Android通知
    • 2.1、创建通知渠道(Android 8.0+ 必需)​
    • 2.2、发送基础通知​
    • 2.3、在Activity中调用
  • 3、Android前台服务
    • 3.1、创建前台服务类(MyForegroundService.java)​
    • 3.2、在 AndroidManifest.xml 中注册服务和权限​
    • 3.3、从 Activity 启动服务​
    • 3.4、停止服务
    • 3.5、注意事项​​

1、Android服务

1.1、定义

  • 服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务
  • 服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
  • 服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。 耗时操作需另启线程(如HandlerThread或AsyncTask)

1.2、基本用法

1.2.1、定义一个服务

  • 要创建服务,您必须创建 Service 的子类或使用其现有子类之一
  • onBind()方法。这个方法是Service中唯一的一个抽象方法,所以必须要在子类里实现。
  • onCreate()方法会在服务创建的时候调用,onStartCommand()方法会在每次服务启动的时候调用,onDestroy()方法会在服务销毁的时候调用。
  • 如果希望服务一旦启动就立刻去执行某个动作,就可以将逻辑写在onStartCommand()方法里
public class MyService extends Service {private static final String TAG = "MyService";private Handler handler;private Runnable task;@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "服务创建");// 初始化Handler和定时任务(示例:每秒打印日志)handler = new Handler(Looper.getMainLooper());task = new Runnable() {@Overridepublic void run() {Log.d(TAG, "服务运行中: " + System.currentTimeMillis());handler.postDelayed(this, 1000); // 每隔1秒执行一次}};}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "服务启动");handler.post(task); // 启动定时任务return START_STICKY; // 服务被终止后自动重启}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "服务销毁");handler.removeCallbacks(task); // 停止任务,避免内存泄漏}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null; }
}

1.2.2、服务注册

  • 每一个服务都需要在AndroidManifest.xml文件中进行注册才能生效
<application><service android:name=".MyService" android:enabled="true" />
</application>

1.2.3、启动和停止服务

  • 启动和停止的方法主要是借助Intent来实现的
  • startService()和stopService()方法都是定义在Context类中的,所以我们在活动里可以直接调用这两个方法。
  • onCreate()方法是在服务第一次创建的时候调用的,而onStartCommand()方法则在每次启动服务的时候都会调用。
  • 服务应在工作完成后通过调用 stopSelf() 停止自身,或者另一个组件可以通过调用 stopService() 停止它。
//从Activity启动/停止服务​
// 启动服务
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);// 停止服务
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);

1.2.4、活动和服务进行通信

  • 应用组件(例如 activity)可以通过调用 startService() 并传入指定服务并包含服务要使用的任何数据的 Intent 来启动服务。服务会在 onStartCommand() 方法中接收此 Intent。
  • 当一个活动和服务绑定了之后,就可以调用该服务里的Binder提供的方法了

1.3、带绑定的服务示例

  • 用于活动和服务进行通信,比如在活动中指挥服务去看什么,服务就去干什么,主要用onBind()方法
  • 当一个活动和服务绑定之后,就可以调用该服务里的Binder提供的方法了。

示例说明:

  1. 在服务类中定义Binder的内部类,此内部类定义获取服务实例的函数,以供活动中调用;
  2. 在活动中定义ServiceConnection匿名类在重写的方法中服务的实例;
  3. 获取到服务实例后,就可以调用服务定义的方法。

1.3.1、定义服务类

public class MyService extends Service {private static final String TAG = "MyService";private Handler handler;private Runnable task;private int counter = 0; // 示例:用于客户端交互的计数器// 1. 定义 Binder 类public class MyBinder extends Binder {public MyService getService() {return MyService.this; // 返回当前服务实例}}private final IBinder mBinder = new MyBinder(); // Binder 对象@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "服务创建");handler = new Handler(Looper.getMainLooper());task = new Runnable() {@Overridepublic void run() {Log.d(TAG, "服务运行中: " + System.currentTimeMillis());handler.postDelayed(this, 1000);}};}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, "服务启动");handler.post(task);return START_STICKY;}// 2. 实现绑定功能@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "客户端绑定");return mBinder; // 返回 Binder 对象}@Overridepublic boolean onUnbind(Intent intent) {Log.d(TAG, "所有客户端解绑");return super.onUnbind(intent);}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "服务销毁");handler.removeCallbacks(task);}// 3. 定义客户端可调用的方法public int getCounter() {return counter++;}public String formatMessage(String input) {return "服务处理: " + input.toUpperCase();}
}

1.3.2、客户端(Activity)绑定与交互​

public class MainActivity extends AppCompatActivity {private MyService myService;private boolean isBound = false;// 1. 定义 ServiceConnectionprivate ServiceConnection connection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {MyService.MyBinder binder = (MyService.MyBinder) service;myService = binder.getService(); // 获取服务实例isBound = true;Log.d("Client", "绑定成功,计数器值: " + myService.getCounter());}@Overridepublic void onServiceDisconnected(ComponentName name) {isBound = false;}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 2. 绑定服务Intent intent = new Intent(this, MyService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}// 3. 调用服务方法(示例:按钮点击事件)public void onButtonClick(View view) {if (isBound) {String result = myService.formatMessage("hello");Toast.makeText(this, result + " 计数:" + myService.getCounter(), Toast.LENGTH_SHORT).show();}}@Overrideprotected void onDestroy() {super.onDestroy();// 4. 解绑服务if (isBound) {unbindService(connection);isBound = false;}}
}

1.3.3、AndroidManifest.xml 注册​

<service android:name=".MyService" android:enabled="true" />

1.3.4、关键点

  • ​​Binder 机制​​

    • 通过继承 Binder类实现内部类,提供 getService()方法返回服务实例。
    • 客户端通过 ServiceConnection获取 IBinder对象并转换为具体类型。
  • ​​生命周期管理​​

    • 绑定触发顺序:onCreate()→ onBind();解绑触发 onUnbind()→ onDestroy()(若无其他绑定)。
    • 必须调用 unbindService()避免内存泄漏(通常在 onDestroy()中处理)。
  • ​​线程安全​​

    • 服务方法默认在主线程执行,若需耗时操作应另启线程(如 HandlerThread)

2、Android通知

2.1、创建通知渠道(Android 8.0+ 必需)​

private void createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {String channelId = "my_channel_id";CharSequence name = "My Channel";String description = "Default Notification Channel";int importance = NotificationManager.IMPORTANCE_DEFAULT;NotificationChannel channel = new NotificationChannel(channelId, name, importance);channel.setDescription(description);NotificationManager notificationManager = getSystemService(NotificationManager.class);notificationManager.createNotificationChannel(channel);}
}

2.2、发送基础通知​

private void sendSimpleNotification(Context context) {// 1. 获取NotificationManagerNotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);// 2. 创建点击通知后跳转的IntentIntent intent = new Intent(context, TargetActivity.class);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);// 3. 构建通知NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "my_channel_id").setSmallIcon(R.drawable.ic_notification) // 必需的小图标.setContentTitle("新消息提醒")              // 通知标题.setContentText("这是一条简单的通知示例")   // 通知内容.setPriority(NotificationCompat.PRIORITY_DEFAULT) // 优先级.setContentIntent(pendingIntent)         // 设置点击行为.setAutoCancel(true);                    // 点击后自动消失// 4. 发送通知(ID唯一,可用于更新或取消)notificationManager.notify(1, builder.build());
}

2.3、在Activity中调用

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);createNotificationChannel(); // 初始化通知渠道findViewById(R.id.btn_send).setOnClickListener(v -> {sendSimpleNotification(this); // 点击按钮发送通知});
}

3、Android前台服务

  • ​Android 8.0+限制​​:后台服务需使用startForeground()并显示通知,否则会被系统回收

3.1、创建前台服务类(MyForegroundService.java)​

public class MyForegroundService extends Service {private static final String TAG = "MyForegroundService";private static final String CHANNEL_ID = "foreground_service_channel";private static final int NOTIFICATION_ID = 1;@Overridepublic void onCreate() {super.onCreate();createNotificationChannel(); // 创建通知渠道(Android 8.0+必需)}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// 构建通知Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID).setContentTitle("前台服务运行中").setContentText("正在执行后台任务...").setSmallIcon(R.drawable.ic_notification) // 必需的小图标.setPriority(NotificationCompat.PRIORITY_DEFAULT).build();// 将服务提升为前台服务startForeground(NOTIFICATION_ID, notification);Log.d(TAG, "前台服务已启动");// 模拟任务(实际可替换为下载、播放等逻辑)new Thread(() -> {while (true) {try {Thread.sleep(1000);Log.d(TAG, "任务执行中...");} catch (InterruptedException e) {e.printStackTrace();}}}).start();return START_STICKY; // 服务被终止后自动重启}// 创建通知渠道(Android 8.0+)private void createNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"前台服务通知",NotificationManager.IMPORTANCE_DEFAULT);NotificationManager manager = getSystemService(NotificationManager.class);manager.createNotificationChannel(channel);}}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null; // 不提供绑定功能}@Overridepublic void onDestroy() {super.onDestroy();Log.d(TAG, "服务已停止");}
}

3.2、在 AndroidManifest.xml 中注册服务和权限​

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /><application><serviceandroid:name=".MyForegroundService"android:enabled="true"android:exported="false" />
</application>

3.3、从 Activity 启动服务​

// 启动前台服务(兼容 Android 8.0+)
Intent serviceIntent = new Intent(this, MyForegroundService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {startForegroundService(serviceIntent); // Android 8.0+ 专用方法
} else {startService(serviceIntent);
}

3.4、停止服务

// 停止服务
Intent stopIntent = new Intent(this, MyForegroundService.class);
stopService(stopIntent);

3.5、注意事项​​

  • 通知渠道​​:Android 8.0 及以上版本必须创建通知渠道,否则通知无法显示。
  • ​​5秒规则​​:调用 startForegroundService()后需在5秒内调用 startForeground(),否则会触发 ANR。
  • ​​权限​​:Android 10+ 需在清单中声明 FOREGROUND_SERVICE权限。
  • 线程管理​​:前台服务默认在主线程运行,耗时操作需另启线程(如示例中的 Thread)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/92070.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/92070.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/92070.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从基础功能到自主决策, Agent 开发进阶路怎么走

Agent 开发进阶路线大纲基础功能实现核心模块构建环境感知&#xff1a;传感器数据处理&#xff08;视觉、语音、文本等输入&#xff09;基础动作控制&#xff1a;API调用、硬件驱动、简单反馈机制状态管理&#xff1a;有限状态机&#xff08;FSM&#xff09;或行为树&#xff0…

《动手学深度学习》读书笔记—9.6编码器-解码器架构

本文记录了自己在阅读《动手学深度学习》时的一些思考&#xff0c;仅用来作为作者本人的学习笔记&#xff0c;不存在商业用途。 正如我们在9.5机器翻译中所讨论的&#xff0c;机器翻译是序列转换模型的一个核心问题&#xff0c;其输入和输出都是长度可变的序列。为了处理这种类…

DocBench:面向大模型文档阅读系统的评估基准与数据集分析

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; 一、数据集概述与核心目标 DocBench 是由研究团队于2024年提出的首个…

Python高级排序技术:非原生可比对象的自定义排序策略详解

引言&#xff1a;超越原生比较操作的排序挑战在Python数据处理中&#xff0c;我们经常需要处理不原生支持比较操作的对象。根据2024年《Python开发者生态系统报告》&#xff0c;在大型项目中&#xff0c;开发者平均需处理28%的自定义对象排序需求&#xff0c;这些对象包括&…

低代码系统的技术深度:超越“可视化操作”的架构与实现挑战

在很多非开发者眼中&#xff0c;低代码平台似乎只是简化流程、快速搭建页面的工具。然而&#xff0c;在真实的企业级应用中&#xff0c;低代码系统必须面对高并发请求、复杂业务规则、多角色权限、跨系统集成与持续演进等一系列工程挑战。高效交付&#xff08;Rapid Delivery&a…

【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - 词云图-微博评论词云图实现

大家好&#xff0c;我是java1234_小锋老师&#xff0c;最近写了一套【NLP舆情分析】基于python微博舆情分析可视化系统(flaskpandasecharts)视频教程&#xff0c;持续更新中&#xff0c;计划月底更新完&#xff0c;感谢支持。今天讲解词云图-微博评论词云图实现 视频在线地址&…

Webpack核心技能:Webpack安装配置与模块化

一、webpack 的安装和使用1. webpack 简介webpack 是基于模块化的打包 (构建)工具&#xff0c;它把一切视为模块&#xff08;包括 JS、CSS、图片等资源文件&#xff09;。工作原理&#xff1a;以开发时态的入口模块为起点递归分析所有依赖关系经过压缩、合并等处理最终生成运行…

数据结构---二级指针(应用场景)、内核链表、栈(系统栈、实现方式)、队列(实现方式、应用)

一、二级指针的应用场景1、在被调函数中&#xff0c;想要修改主调函数中的指针变量&#xff0c;需要传递该指针变量的地址&#xff0c;形参用二级指针接收。2、指针数组的数组名是一个二级指针&#xff0c;指针数组的数组名作为参数传递时&#xff0c;可用二级指针接收。指针数…

NodeJs学习日志(1):windows安装使用node.js 安装express,suquelize,sqlite,nodemon

windows安装使用node.js 安装express&#xff0c;suquelize&#xff0c;sqlite 系统是win10&#xff0c;默认已经安装好nodejs与npm包名作用expressWeb应用框架suquelize数据库ORMsqlite数据库nodemon代码热重载安装express 添加express生成器 npm add express-generator4安装e…

Cervantes:面向渗透测试人员和红队的开源协作平台

Cervantes 是一个专为渗透测试人员和红队打造的开源协作平台。它提供了一个集中式工作区&#xff0c;用于集中管理项目、客户端、漏洞和报告。通过简化数据组织和团队协调&#xff0c;它有助于减少规划和执行渗透测试所需的时间和复杂性。 作为 OWASP 旗下的开源解决方案&…

[Python 基础课程]猜数字游戏

使用 Python 实现一个猜数字游戏&#xff0c;先随机生成一个 1 到 100 之间的一个随机整数&#xff0c;让用户猜测这个数是什么&#xff0c;每次都提示用户猜大了还是猜小了&#xff0c;如果用户猜对了&#xff0c;提示用户猜对了&#xff0c;用了多少次&#xff0c;并且之前每…

文件加密实现

一、不依赖外部库实现 使用自定义的XOR加密算法结合简单的密钥扩展。 实现说明 这个方案不依赖任何外部库&#xff0c;仅使用C标准库实现&#xff1a; 加密原理&#xff1a;采用XOR加密算法&#xff0c;这是一种简单但有效的对称加密方式&#xff0c;相同的密钥可以用于加密和解…

Unity轻量观察相机

一、脚本功能简介ObserveCamera 是一个可直接挂载到任意 GameObject 上的通用摄像机控制脚本&#xff0c;支持以下功能&#xff1a;鼠标右键控制摄像机绕自身旋转&#xff08;俯仰、水平&#xff09;鼠标左键拖拽目标对象进行平移&#xff08;局部 XY 平面移动&#xff09;鼠标…

1深度学习Pytorch-pytorch、tensor的创建、属性、设备和类型转换、数据转换、常见操作(获取元素、元素运算、形状改变、相乘、广播)

文章目录PyTorchTensor1 Tensor 的创建1.torch.tensor2.torch.Tensor3. 线性张量4. 随机张量5. 特定数值的张量2 Tensor 常见属性1 属性2 设备切换3 类型转换torch.Tensor.to(dtype)类型专用方法创建张量时直接指定类型与 NumPy 数组的类型互转4 数据转换&#xff08;浅拷贝与深…

五、Istio管理网格外部服务

因语雀与csdn markdown 格式有区别&#xff0c;请查看原文&#xff1a; https://www.yuque.com/dycloud/pss8ys 一、Egress Listener 流量策略 前面学习了 sidecar 自动注入原理、inbound Listener、outbound Listener 等概念&#xff0c;也知道了 EgressListener 的流量策略…

Ubuntu20.04 离线安装 FFmpeg 静态编译包

系统版本 Ubuntu20.04 去现场部署项目&#xff0c;发现现场的设备连接的内网&#xff0c;无法使用apt直接安装ffmpeg &#xff0c;想解决也简单&#xff0c;数据线连接手机使用共享网络&#xff0c;再使用命令sudo apt install ffmpeg安装即可&#xff0c;奈何现场百多台设备&a…

C语言高级编程技巧与最佳实践

C语言高级编程技巧与最佳实践 - 完整版 目录 宏定义与预处理技巧内存管理高级技巧函数指针与回调机制数据结构设计并发与多线程错误处理与异常机制性能优化技巧调试与测试技巧跨平台编程安全编程实践综合演示示例 宏定义与预处理技巧 1. 条件编译与平台检测 /*** 平台和编译…

cygwin+php教程(swoole扩展+redis扩展)

cygwin 1.下载cygwin安装程序 &#xff1a;在Windows上获得Linux的感觉 ​ 2. 打开安装包&#xff1a;setup-x86_64.exe 3.选择安装类型 从互联网安装首次安装下载而不安装仅下载软件包不安装从本地目录安装迁移程序时使用 4.选择安装目录 5.选择本地软件包目录&#xff…

Ethereum: Uniswap V3核心”Tick”如何引爆DEX的流动性革命?

大家好&#xff0c;今天&#xff0c;我们来聊聊一个在去中心化交易所&#xff08;DEX&#xff09;领域&#xff0c;尤其是自Uniswap V3问世以来&#xff0c;变得至关重要的概念——Tick&#xff08;流动性边界&#xff09;。 如果大家接触过DeFi&#xff0c;可能听说过Uniswap …

【概念学习】什么是深度学习

人工智能 人工智能的简洁定义如下&#xff1a;努力将通常由人类完成的智力任务自动化。 因此&#xff0c;人工智能是一个综合性的领域&#xff0c;不仅包括机器学习与深度学习&#xff0c;还包括更多不涉及学习的方法。 在相当长的时间内&#xff0c;许多专家相信&#xff0c;只…