Android 四大组件之 Service (上)

【Dify精讲】第2章:后端服务架构深度剖析 Dify后端采用Flask应用工厂模式实现模块化开发,通过蓝图架构将API分为控制台、Web应用和服务接口三大模块。其设计亮点包括:1) 应用工厂模式支持多环境配置和独立测试;2) 蓝图分层管理实现API模块化,各模块职责清晰;3) 严格遵循RESTful原则设计API接口;4) 使用Flask-RESTful扩展简化API开发。这种架构既保持了Flask的灵活性,又实现了企业级应用的可维护性,是Flask项目架构的优秀实践案例。 阅读详情

       Android 有四大组件,这是每一个 Android 开发者一开始就知道的,也是 Android 基础中的重中之重,是构成 Android 的基石,但相信并不是每一个人都对服务非常的了解,今天我们一起来探究 Android 四大组件之一 Service(服务),对服务进行详细的剖析,来看一看这个运行在后台的默默无闻的工作者



一、服务的概念


       服务(Service)是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件,服务可以由其他应用组件启动,而且即使用户切换到其他应用,服务仍然能够在后台继续运行,此外组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信(IPC),它非常适合去执行那些不需要和用户进行交互,长期运行在后台的一些任务,服务的运行不依赖与任何用户界面,即使用户切换到另外其他的程序,或者切换到后台,服务仍然能够正常运行,例如服务可以处理网络事务、播放音乐、执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行

  • 注意:服务本身并不是运行在一个独立的进程当中,依赖于创建服务时所在的应用程序进程,当服务程序被杀掉时,所依赖进程的服务也会相应的停止运行
  • 服务不是线程,他不是一种来完成主线程之外工作的手段(以避免应用程序没有响应错误)

二、服务的基本用法


我们来新建一个 ServiceTest 项目,进行服务相关的演示


1. 首先我们来创建一个 MyService


/**
 * 定义一个 Service
 */
public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

       我们可以看到,MyService 是继承自 Service 类的,说明它是一个服务,我们看到这个 MyService 里面基本什么也没有,有一个空的构造方法,还有一个 onBind() 方法,打开 Service 的源码我们可以看到 onBind() 是一个必须在子类实现的抽象方法:


    @Nullable
    public abstract IBinder onBind(Intent intent);

       接下来我们要进行逻辑的编写,就必须调用 Service 类中的其他方法,这里我们先重写父类的 onCreate()、onStartCommand、onDestroy() 方法如下:


/**
 * 定义一个 Service
 */
public class MyService extends Service {

    private static final String TAG = "MyService";

    public MyService() {
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     * 在服务第一次创建的时候调用
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    /**
     * 每次服务启动的时候调用
     *
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 销毁服务时调用
     * 在这里可以回收不在使用的资源
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

       这 3 个方法是服务中最常用的方法,其中 onCreate() 方法在服务创建的时候调用,onStartCommand() 方法服务每次启动的时候都会调用,服务销毁的时候调用 onDestroy() 方法,通常情况下,我们如果一旦服务启动就需要去执行某些操作,逻辑就可以写在 onStartCommand() 方法中,同时我们还要注意在 onDestroy() 方法中释放不需要的资源,另外还需要注意,服务时需要在 AndroidManifest.xml 文件中注册的,只是我们的 Android Studio 太智能了,已经自动帮我们注册好了如下,但我们还是要知道:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.qiudengjiao.servicetest">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

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

</manifest>

到这里,我们的服务就算定义完了


2. 启动和停止服务


和 Activity 一样,服务的启动和停止也是借助 Intent 来实现的,接下来我们来开始演绎

我们先在 activity_main.xml 中来定义两个按钮,一个来控制启动,一个来控制停止如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.qiudengjiao.servicetest.MainActivity">

    <Button
        android:id="@+id/start_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="startService"
        android:text="开启服务" />

    <Button
        android:id="@+id/stop_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="stopService"
        android:text="停止服务" />
</LinearLayout>

接着我们来看 MainActivity 中的代码:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * 开启服务
     */
    public void startService(View view) {
        Intent startIntent = new Intent(this, MyService.class);
        //启动服务
        startService(startIntent);
    }

    /**
     * 停止服务
     */
    public void stopService(View view) {
        Intent stopService = new Intent(this, MyService.class);
        //停止服务
        stopService(stopService);
    }
}

       这里看到,我们通过构建 Intent 对象,并调用 startService() 和 stopService() 来启动和停止服务,因为 startService() 和 stopService()方法都是定义在 Context 类中的,所以在 Activity 中我们可以直接调用,需要注意的是,这里完全是由 Activity 来决定服务何时停止的,如果不点击停止服务按钮,服务就会一直处于运行状态,,如果需要服务自己停下来,需要在 Myservice 中调用 stopSelf() 方法,说了这么多,我们来点击开启和停止服务分别来看看日志的打印情况,看是否和我们描述的一样:

点击开启服务日志打印情况:




点击停止服务日志打印情况:




从日志的打印情况和我们的描述是一模一样的,也验证了我们的想法


3. 活动和服务进行通信


       在上面 1 和 2 中我们介绍了 Service 的基本用法,当启动 Service 后,就可以在 onCreate() 或者 onStartCommand() 方法里去执行具体的逻辑操作,那么我们如何才能把 Activity 和 Service 关联起来,进行通信,这样我们就能在 Activity 中来控制 Service,这里就需要用到我们一开始创建 Service 时就必须强制实现父类的 onBind() 方法,其实这个方法就是用于和 Acitivity 进行关联的

       例如我们希望在 MyService 里面提供一个下载功能,然后活动中可以决定何时开始下载,以及随时查看下载进度,实现这个功能的思路是可以创建一个专门的 Binder 对象对下载功能进行管理,接下来我们修改 MyService 中的代码代码如下所示:


/**
 * 定义一个 Service
 */
public class MyService extends Service {

    private static final String TAG = "MyService";


    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder {
        //模仿方法
        public void startDownload() {
            // 执行具体的下载任务
            Log.d(TAG, "startDownload");
        }

        //模拟加载进度
        public int getProgress() {
            Log.d(TAG, "getProgress");
            return 0;
        }
    }

    public MyService() {
    }


    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    /**
     * 在服务第一次创建的时候调用
     */
    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
    }

    /**
     * 每次服务启动的时候调用
     *
     * @param intent
     * @param flags
     * @param startId
     * @return
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 销毁服务时调用
     * 在这里可以回收不在使用的资源
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }
}

       可以看到我们在 MyService 里新建了一个 DownloadBinder 类,并让它继承自 Binder,然后在它的内部提供了开始下载以及查看进度的方法,当然我们这里只是提供模拟的方法,并没有真正的去实现它对应的功能,接着在 MyService 中创建了 DownloadBinder 的实例,然后再 onBind() 方法里返回了这个实例,到这里 MyService 中的工作就全部完成

接下来我们在布局文件添加两个按钮去调用服务里的方法,我们来修改 activity_main.xml 中的代码如下:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.qiudengjiao.servicetest.MainActivity">

    <Button
        android:id="@+id/start_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="startService"
        android:text="开启服务" />

    <Button
        android:id="@+id/stop_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="stopService"
        android:text="停止服务" />

    <Button
        android:id="@+id/bind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="bindService"
        android:text="绑定服务" />

    <Button
        android:id="@+id/unbind_service"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="unBindService"
        android:text="解绑服务"
        />
</LinearLayout>

       这两个按钮分别是用来绑定和解绑服务的,那么到底需要谁去和服务绑定呢,当然是活动,当一个服务和活动绑定之后,就可以调用该服务里 Binder 提供的方法,我们修改 MainActivity 中的代码:


public class MainActivity extends AppCompatActivity {

    private MyService.DownloadBinder downloadBinder;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            downloadBinder = (MyService.DownloadBinder) service;
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    /**
     * 开启服务
     */
    public void startService(View view) {
        Intent startIntent = new Intent(this, MyService.class);
        //启动服务
        startService(startIntent);
    }

    /**
     * 停止服务
     */
    public void stopService(View view) {
        Intent stopService = new Intent(this, MyService.class);
        //停止服务
        stopService(stopService);
    }


    /**
     * 绑定服务
     */
    public void bindService(View view) {
        Intent bindIntent = new Intent(this, MyService.class);
        //绑定服务
        bindService(bindIntent, connection, BIND_AUTO_CREATE);
    }

    /**
     * 解绑服务
     */
    public void unBindService(View view) {
        //解绑服务
        unbindService(connection);
    }
}


这里我们首先创建了创建了一个 ServiceConnection 的匿名类,并重写了 onServiceConnected() 和 onServiceDisconnected() 方法

  • onServiceConnected():活动与服务绑定时调用
  • onServiceDisconnected():活动与服务解除绑定时调用

       在 onServiceConnected() 方法中我们通过向下转型得到 DownloadBinder 的实例,这个实例保证了活动与服务之间的紧密连接,这样我们就能在活动中根据具体的场景来调用 DownloadBinder 中的任何 public 方法了

       当然,现在活动还没有和服务进行绑定,这个功能是在绑定服务的按钮的点击事件里完成的,可以看到这里我们任然构建了一个 Intent 对象,然后调用 bindService() 方法进行绑定,bindService() 方法接受 3 个参数,第一个参数就是刚刚构建的 Intent 对象,第二个参数是前面创建出的 ServiceConnection 的实例,第三个参数则是一个标志位,这里传入 BIND_AUTO_CREATE 表示在活动和服务绑定之后自动创建服务,这会使得 MyService 中的 onCreate() 方法得到执行,但是 onStartCommand() 方法不会执行,点击解绑服务按钮,调用 unbindService() 方法,就可以解除活动和服务之间的绑定

现在我们来运行下程序,点击绑定服务按钮,看我们的日志打印情况:



       

       可以看到,首先是 MyService 的 onCreate() 方法得到了执行,然后 startDownload() 方法和 getProgress() 方法得到执行,说明我们成功的在活动里调用了服务里提供的方法

       另外需要注意:任何一个服务在整个应用程序范围内都是通用的,即 MyService 不仅可以和 MainActivity 绑定,还可以和任何一个其他的活动进行绑定,而且绑定完成后都可以获取到相同的 DownloadBinder 实例


4.服务的生命周期


1)管理服务的生命周期


       服务的生命周期比 Activity 的生命周期要简单得多,但是,密切关注如何创建和销毁服务反而更加重要,因为服务可以在用户没有意识到的情况下运行于后台

服务的生命周期(从创建到销毁)可以遵循两条不同的路径:

  • 启动服务

       该服务在其他组件调用 startService() 时创建,然后无限期运行,且必须通过 stopSelf() 来自行停止运行,此外,其他组件也可以通过调用 stopService 来停止服务,服务停止后,系统会将其销毁

  • 绑定服务

       该服务在另一个组件(客户端)调用 bindService() 时创建,然后,客户端通过 IBinder 接口与服务进行通信,客户端可以调用 unbindService() 关闭连接,多个客户端可以绑定到相同的服务,而且当所有绑定全部取消后,系统即会销毁该服务,(服务不必自行停止运行)

       这两条路并非完全独立,也就是说,你可以绑定到已经使用 startService() 启动的服务,例如,可以通过使用 Intent (标识要播放的音乐),调用 startService() 来启动后台音乐服务,随后,可能在用户需要稍加控制播放器获取有关当前播放歌曲的信息是,Activity 可以调用 bindService() 绑定到服务,在这种情况下,除非所有客户端均取消绑定,否则 stopService() 或 stopSelf() 不会实际停止服务


2)实现生命周期回调


       与 Activity 类似,服务也拥有生命周期的回调方法,你可以实现这些方法来监控服务状态的变化并适时执行相应的操作,以下框架服务展示了每种生命周期方法,来自 Google 官网:


public class ExampleService extends Service {
    int mStartMode;       // indicates how to behave if the service is killed
    IBinder mBinder;      // interface for clients that bind
    boolean mAllowRebind; // indicates whether onRebind should be used

    @Override
    public void onCreate() {
        // The service is being created
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // The service is starting, due to a call to startService()
        return mStartMode;
    }
    @Override
    public IBinder onBind(Intent intent) {
        // A client is binding to the service with bindService()
        return mBinder;
    }
    @Override
    public boolean onUnbind(Intent intent) {
        // All clients have unbound with unbindService()
        return mAllowRebind;
    }
    @Override
    public void onRebind(Intent intent) {
        // A client is binding to the service with bindService(),
        // after onUnbind() has already been called
    }
    @Override
    public void onDestroy() {
        // The service is no longer used and is being destroyed
    }
}

接下来看看服务的生命周期图,来自 Google 官网:



注意:与 Activity 生命周期回调方法不同,你不需要调用这些回调方法的超类实现


       上图,左边显示了使用 startService() 所创建的服务的生命周期,右图显示了使用 bindService() 所创建的服务的生命周期,通过实现这些方法,你可以监控服务生命周期的两个嵌套循环:

  • 服务的整个生命周期从调用 onCreate() 开始,到 onDestroy() 返回结束,与 Activity 类似,服务也在 onCreate() 方法中完成初始化设置,并在 onDestroy() 方法中释放所剩余资源,例如音乐播放器播放服务可以在 onCreate() 中创建用于播放音乐的线程,然后在 onDestroy() 方法中停止该线程,无论服务是通过 startService() 还是 bindService() 创建,都会为所有服务调用 onCreate() 和 onDestroy() 方法
  • 服务的有效生命周期从调用 onStartCommand() 或 onBind() 方法开始每种方法均有 Intent 对象,该对象分别传递到 startService() 或 bindService(),对于启动服务,有效生命周期与整个生命周期同时结束(即便是在 onStartCommand() 返回之后,服务任然处于活动状态)对于绑定服务,有效生命周期在 onUnbind() 返回时结束


注意:尽管启动服务是通过调用 stopSelf() 或 stopService() 来停止,但该服务并无相应的回调(没有 onStop() 回调)因此,除非服务绑定到客户端,否则在服务停止时,系统会通过 onDestroy() 将其销毁


5. 如何销毁 Service


上面我们分析了 Service 两种情况的生命周期,我们总结一下销毁 Service 的各种情况


1)点击开启服务按钮,再点击停止服务按钮,这样 Service 就被销毁了,我们来看日志情况:


点击开启服务:




点击停止服务:




2)如果我们点击的是绑定服务按钮,那么就需要点击解绑服务按钮来销毁服务,来看看是具体什么执行情况:


点击绑定服务按钮:




点击解绑服务按钮:





3)以上两种销毁方式比较好理解,接下来如果我们先点击开启服务按钮,再点击绑定服务按钮,然后点击停止服务按钮,这样会怎么样呢?这时我们发现,不管我们是单独点击停止服务按钮,还是单独点击解绑服务按钮,Service 都不会销毁,必须两个按钮都点击一下,Service 才会被销毁,这种现象说明,点击停止服务按钮只能让 Service 停止,点击解绑服务按钮只会让 Service 和 Activity 解除关联,要想让 Service 销毁,必须既没有和任何 Activity 关联,又处于停止状态的时候,接下来我们来看看日志的打印情况,以验证我们上面的说法:


点击开启服务按钮:




再点击绑定服务按钮:




点击停止服务按钮:




这里看到点击停止服务按钮,服务并没有停止,我们接下来再点击解绑服务按钮:



这时候我们看到服务才停止了


今天就先写到这里,如有错误请指出,大家周末愉快


参考:Google 官网,郭神第一行代码



ARM6818嵌入式视频播放器:硬解加速与Framebuffer渲染实战 嵌入式Linux音视频系统是智能座舱、工业HMI等场景的核心能力,其本质是软硬协同的实时多媒体处理系统。原理上需打通内核驱动(如VPU硬件编解码、FIMD多图层合成)、用户空间框架(GStreamer pipeline定制、SDL2硬件渲染)与应用层同步机制(PTS/HTS双时钟校准)。技术价值在于显著降低CPU负载(硬解可压至15%以下)、提升启动速度(<1.2s首帧)并保障音画同步精度(±3ms级)。典型应用场景包括车载信息娱乐、边缘AI终端及无X11的工控显示设备。本文基于ARM6818平台,深入VP 阅读详情

相关推荐

用Multisim仿真AD630锁定放大器:从2012年电赛A题实战到避坑指南

本文详细介绍了如何使用Multisim仿真AD630锁定放大器,从2012年电赛A题实战出发,提供完整的电路搭建、参数优化及避坑指南。重点解析AD630的开关调制架构和双相位检测的工程实现,帮助读者在强噪声背景下有效提取微弱信号,提升电子设计竞赛和工程实践中的信号处理能力。

weixin_42549451的博客 203

Android Studio的代码笔记--DownloadManager强制下载

DownloadManager强制下载AlertDialog无法取消窗口dialog.xmlDialogDownMainActivity中的使用DownloadManager 下载DownApkMainActivity中的使用BroadcastReceiver安装apkInstallApk静态广播添加权限 AlertDialog无法取消窗口 dialog.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro

weixin_45208598的博客 656

Yolov2 训练时anchor是如何使用的?build_target

0.简略描述 1.将真值检测框变换到特征图尺度上 2.计算以特征图每个网格中心为中心点时所有锚框与真值检测框的交并比 3.取与真值检测框交并比最大的锚框的id,及真值检测框中心所在cell的id,有此,可将真值检测框与预测结果对应起来 4.计算位置回归损失,置信度损失,分类损失 1,网络的输出 图1 yolov2 网络对于检测框位置大小的输出是: 对于1个batch网络的输出的shape为[batch_size, H*W*num_anchors, 5+num_classes], 其中: num_

机器人视觉感知 2818

Android从1.0到 6.0各版本的差别

Android 系统从2008年到现在(2016年4月),八年时间里版本从1.0一直升到6.0,由于Android系统更新速度快,导致市面上的Android设备运行的Android系统版本不一(专业术语叫碎片化严重)从图中可以知道目前主流的系统是三款,但是还是有些版本的系统还在使用,作为Android程序开发者,必须尽量照顾到各种版本的系统,否则你提出的解决方案是不完善的,对于Android开发者来说,很有必要知道android各个版本的特性,这样才能制定出更完备的软件开发方案。这样才能开发出可以稳定运行在

Android 小生的博客 4万+

OpenClaw与Ollama本地AI部署指南

AI模型本地化部署是当前企业数字化转型的关键技术,通过开源框架Ollama可以在消费级硬件上运行大语言模型。本文以OpenClaw多智能体系统为例,详解从环境配置到模型优化的全流程实践,特别针对国内开发者遇到的网络问题提供了镜像加速等解决方案。这种私有化部署方案尤其适合金融数据分析、企业知识管理等对数据安全要求高的场景,通过模块化设计实现多智能体协作,同时保持对NVIDIA显卡和普通CPU的兼容性。

weixin_34302561的博客 398

在x86机器上运行jailhouse

jailhouse jaihouse提供了一个demo ,https://github.com/siemens/jailhouse-images可以用于编译一整套可用的demo。 适用于多个平台。编译过程主要参考https://blog.youkuaiyun.com/weixin_39541632/article/details/110422345 此demo可以生成多个平台所用的操作系统image。 ...

闲人的专栏 3005

【Android】安卓四大组件之Service

【Android】安卓四大组件之Service 1、Service的介绍 1.1 什么是service Service即服务,用大白话讲就是——长期运行在后台的程序,如果我们说的官方一点,那么就是用于执行长期运行的任务,并且没有与用户交互的功能。 每一个service都和activity一样,需要在manifest.xml中配置,赋予其生命。使用<service>标签即可配置 在activity类中,可以使用Context.startService()方法来开启服务,使用Context.stop

woodwhale的博客 690

基准电压 + 运放 + 低边MOS恒流源控制原理

因为恒流源强制 Iout不变,而 Vin​ 增加时,负载压降 Iout⋅Rload不变,多余的电压只能由MOS管的 VDS承担,因此 VDS必然增加。在饱和区,MOS 管的 ID 仅由 VGS决定,与 VDS 无关,这样,负载变化时,VDS可自由调整以维持 Iout恒定。当 Vin​ 小到无法满足 VDS>VGS−Vth时,MOS管进入线性区,Iout 会随 Vin​ 下降而减小,恒流失效。由于 Vref和 Rsense未变,Iout无需调整,运放无需动作,OUT保持不变,Iout恒定。

weixin_50643237的博客 2655

android四大组件(Activity,Service,BroadcastReceiver,Content Provider)

安卓的四大组建,五大布局Android四大组件:Activity、Service、Broadcast Receiver、Content Provider。1、 Activity 可以去本人博客activity了解学习是Android程序与用户交互的窗口,从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个

Mr_haimeng的博客 1358

STM32 SPI驱动TFT LCD实战:时序配置与硬件协同

SPI(串行外设接口)是一种高速、全双工、同步串行通信协议,广泛应用于微控制器与显示模组等外设的数据交互。其核心依赖时钟极性(CPOL)与时钟相位(CPHA)组合定义的四种工作模式,直接影响数据采样可靠性;而片选(NSS)与MOSI/SCLK等信号的硬件映射,则决定了多设备共总线下的通信稳定性。在TFT LCD驱动场景中,SPI凭借低开销、高吞吐优势成为主流选择,尤其适配ST7789、ILI9341等集成显示控制器的模块。本文聚焦STM32L系列MCU通过SPI2驱动1.3寸LCD的完整链路,涵盖Mode

php55的博客 1209

【Burp入门第三十三篇】BurpSuite+Proxifier安装配置,实现微信小程序抓包

本文介绍Burp+Proxifier安装配置,实现微信小程序抓包

等风来 5873

【Android】安卓四大组件之服务(Service)详解:从基础到进阶

Service作为安卓应用后台任务处理的核心组件,在保障应用功能完整性和提升用户体验方面起着不可或缺的作用。通过掌握Service的生命周期、分类及使用场景,开发者能够合理设计应用架构,实现高效、稳定的后台任务处理。随着安卓系统的不断升级,Service的使用也需与时俱进,结合新特性和替代方案,让应用在后台运行中发挥更大价值。希望本文能帮助大家深入理解Service,在安卓开发中灵活运用这一强大工具

m0_59734531的博客 1522

小程序设计中的区块链应用:数字藏品实现

本文旨在为开发者提供在小程序中实现区块链数字藏品功能的完整技术方案。区块链与数字藏品的基础概念智能合约的设计与实现小程序与区块链的交互方式数字藏品的完整实现流程文章将从基础概念入手,逐步深入到技术实现层面,最后通过完整项目案例展示数字藏品在小程序中的实现方式。每个技术点都会配合代码示例和架构图进行说明。区块链:一种分布式数据库技术,通过加密算法保证数据不可篡改数字藏品:基于区块链技术的数字资产,具有唯一性和可验证性NFT。

小程序开发 1351

【Android】安卓四大组件之Service用法

使用Handler更新UI,基本特点后台执行Service主要用于在后台执行一些长时间运行的操作,比如音乐播放、文件下载等,而不会影响用户界面的交互。

Patrick_yuxuan的博客 1401

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android四大组件之Service

https://developer.android.google.cn/guide/components/services.html本篇博客讲解的是Android四大组件之Service,下面是内容摘要: 了解Service Android 中的进程 电话窃听器 Service 的生命周期 AIDL的使用 一、Service 的基本概念Android 官方文档对Service 的解释如下:A Ser

JackChan 1176

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

安卓四大组件之service

Service作为Android四大组件之一,在每一个应用程序中都扮演着非常重要的角色,所以每一位安卓工程师对其掌握是必然的!针对Service,优快云博客之星–郭霖写了两篇比较完整的解析博客: Android Service完全解析,关于服务你所需知道的一切(上) Android Service完全解析,关于服务你所需知道的一切(下)

探路的淮--Ontheway的博客 953

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

android四大组件应用app,安卓四大组件———Service

1.什么是Service(服务)Service是一种后台运行的应用组件。2.Service有哪些应用场景下载任务,qq消息缓存,音乐播放器的播放3.startService方式启动Service怎么做()首先新建一个类继承Service ,实现它的onBind方法,其中可以用onCreate(),onStartCommand()和onDestroy()方法。例如package com.exampl...

weixin_30395941的博客 513

安卓开发四大组件及Service

对于activity和服务来说,它指明了请求的操作名称以及作为操作对象的数据的URI和其他一些信息。比方说,它能够承载对一个activity 的请求,让它为用户显示一张图片,或者让用户编辑一些文本。广播i接收器没有用户界面,但可以启动一个activity或service来响应收到的信息,或用NotificationManager来通知用户。静态注册无需担忧是否被关闭,只要设备是开启状态,广播接收器也是打开的。使用URI唯一标识其数据集,这里的URI以content://作为前缀,表示数据由其管理。

gfdr5的博客 297

安卓四大组件之Service

Service作为安卓四大组件之一通常用来完成一些不需要用户操作,但是一直运行着的任务  在介绍Service之前 我们先了解一下安卓中进程的优先级: 安卓中的优先级共有5个 1.Foregrounf process 前台进程  当前进程中有Activity处于可见可操作(Activity执行onResume之后) service 以及广播接收者 执行生命周期方法 2.vi

ybx007的博客 512

Android 四大组件之Service

Service是android系统中的四大组件之一(Activity、Service、BroadcastReceiver、ContentProvider),它跟Activity的级别差不多,区别是Service只能运行在后台不提供用户界面,并且可以和其他组件进行交互。一个Service是一个可以长期运行在后台的应用程序组件,不提供用户界面。 另一个应用程序组件可以启动一个服务,它将继续在后台运行,...

ZHS_Vistor的博客 474

安卓四大组件 —— Service

1、什么是service? service是android四大组件之一,是可以在后台长期执行并且没有用户界面的程序组件;只能运行在主线程中,不能做耗时操作,可以跨程序调用。 2、service有哪些应用场景? 当程序中的某项功能执行时间较长(如:下载,上传等)并且在执行过程中不需要用户操作,不需要Activity进行交互的情况下,可以通过service在后台完成指定任务。 3、starSe...

s15770702468的博客 728

Android——四大组件Service

文章目录AndroidAndroid四大组件——Service1 简介2 生命周期3 Service分类3.1 started(启动服务)3.2 bound(绑定服务)IBinder接口ServiceConnection接口 Android Android四大组件——Service service用于在后台完成用户指定的操作。 startService() 与 bindService()区别: (a)started service(启动服务)是由其他组件调用startService()方法启动的,这导致服

weixin_45044097的博客 300

0909Android基础安卓四大组件之Service

服务是什么  服务(Service)是Android中实现程序后台运行的解决方案,它非常适合用于执行那些不需要和用户交互而且还需要长期运行的任务。服务的运行不依赖与用户界面,当程序被切换到后台,或者用户打开另一个应用程序,服务依然正常运行。   服务依赖于创建服务时所在的应用程序进程。某个应用进程被杀掉时,依赖于该进程的服务也停止。服务的生命周期   左图是未绑定的服务的生命周期,右图是绑定服务

DDDebussy的博客 1090

安卓四大组件之一 Service简单实现

1、介绍: Service,服务,是四大组件之一, 和Activity 非常相似, 一般运行在后台, 没有用户界面, 可执行的程序 Activity 和 Service的区别 不同点: 1、Activity : 可以和用户交互, 页面可见 2、Service : 后台运行, 没有界面 相同点: service 的用途:播放音乐;后台下载大文件 2、代码: 主类代码: package com.e...

qq_44946212的博客 416

Android 四大组件基础(Activity/Service/BroadcastReceiver/ContentProvider)工控场景用法

Android四大组件在工控场景中的应用与手机开发有显著差异。工控开发以Service为核心,负责后台数据采集(串口/Modbus)、设备监控等关键任务,需通过前台Service保证持续运行。Activity主要用于全屏数据显示和参数配置,需禁用旋转和返回键退出。BroadcastReceiver实现开机自启、外设状态监听等功能。ContentProvider则用于多应用间共享传感器数据。工控开发强调稳定性,四大组件需针对工业环境特殊配置,如固定屏幕方向、防进程回收等。

爱片闲串,爱钓鱼,爱中医,爱分享 534
上一篇: Retrofit 2.0 基本使用
下一篇: Android 四大组件之 Service (下)
QDJdeveloper
博客等级 码龄11年 108粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值