安卓计步器是如何实现计步的

开发环境

由于要用JAVA开发后端因此JDK必不可少,然后下载androd studio即可。SDK

SDK:软件开发工具包(Software Development Kit)一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。包括广义上指辅助开发某一类软件的相关文档、范例和工具的集合。

Android SDK 就是 Android 专属的软件开发工具包。
主要作用包括:
1.提供基础类库和官方推荐的附加类库
调用电话/调用相机/相册选择等都是由基础类库android.jar提供的v4包v7包都是官方推荐的附加类库
2.编译工具
java编码文件通过编译工具编译成Darvit虚拟机能够读取的dex文件,Android4.4后使用Art虚拟机,运行效率得到极大的提高
3.调试开发工具
提供了模拟器等调试开发工具
需求案例
2018年平安银行产品经理和开发人员打架事件受到广泛的关注,主要是由于不懂技术的产品经理提出奇葩需求:app的主题颜色能够根据手机壳的颜色变化而变化。我们一个需求的实现高度依赖于SDK,SDK提供了相关API我们就能做,如果没有提供我们就做不了,因此该开发人员在拒绝该需求的时候解释说没有提供接口,这里就是说SDK没有提供相关的API来做这个需求。

Android SDK 中提供的面向硬件的特性
android.hardware.Camera
允许应用程序与相机交互的类,可以截取照片、获取预览屏幕的图像,修改用来治理相机操作的参数。
android.hardware.SensorManager
允许访问 Android 平台传感器的类。并非所有配备 Android 的设备都支持SensorManager 中的所有传感器
android.hardware.SensorListener
在传感器值实时更改时,希望接收更新的类要实现的接口。应用程序实现该接口来监视硬件中一个或多个可用传感器。
android.media.MediaRecorder
用于录制媒体样例的类, 可以分析音频片段以便在访问控件或安全应用程序时进行身份鉴定。例如,它可以帮助您通过声音打开门,以节省时间,不需要从房产经纪人处获取钥匙。
android.FaceDetector
允许对人脸(以位图形式包含)进行基本识别的类。不可能有两张完全一样的脸。可以使用该类作为设备锁定方法,无需记密码 — 这是手机的生物特征识别功能。
android.os.*
包含几个有用类的包,可以与操作环境交互,包括电源管理、文件查看器、处理器和消息类。和许多可移动设备一样,支持 Android 的电话可能会消耗大量电能。让设备在正确的时间 “醒来” 以监视感兴趣的事件是在设计时需要首先关注的方面。
java.util.Date
java.util.Timer
java.util.TimerTask
当测量实际的事件时,数据和时间往往很重要。例如,java.util.Date 类允许您在遇到特定的事件或状况时获取时间戳。您可以使用 java.util.Timer 和java.util.TimerTask 分别执行周期性任务或时间点任务

Android SDK 中提供的面向软件的特性
Android作为一个SDK,就需要提供给开发者在开发产品过程中实现一个基本功能所需的基本开发组件,而这些组件就是Activity,Service,Broadcast和ContentProvider

JDK
JDK全称为Java开发工具包,主要作用包括:
1.提供基础类库
由rt.jar提供了基础类的API,如果基础类没有只能由jar包的扩展类来提供
2.JVM[JAVA虚拟机]
class文件通过JVM"翻译"成机器能够识别的二进制的编码,充当着机器和虚拟机之间的桥梁
3.编译器
将java编码"翻译"成JVM能够识别的成class文件
4.调试开发工具
提供debug调试工具等
跨平台
Java之所以能实现其跨平台的属性其JVM功不可没,不管你是win、mac还是Linux系统,只要安装了JDK,就能跨平台运行class文件。JVM做了中间的桥梁,所以JVM是很牛逼的东西,可惜的是我国真正去研究JVM的人很少。

Android SDK和JDK区别和联系
1.Android SDK的基础类库[android.jar]参考了大部分的JDK基础类库[rt.jar],在此基础上进行的一些修减,增加了Android特有的也删除了JDK的一些基础类,也有改造了一些类。Android各版本对应的SDK和JDK版本
2.Android SDK不包括虚拟机但JDK包括虚拟机,Android的Darvit&ART虚拟机安装在Android设备上,Android是不存在main方法的入口这种说法的。
3.Android SDK编译工具[Gradle]是将java文件编译成Darvit&ART虚拟机能够读取的apk文件,JDK编译工具将java文件编译成JVM虚拟机能够读取的class文件。apk文件本质上就是zip包其中类主要编译在dex文件中,dex文件由class文件转化而来,因此apk的编译程序比war包[将class文件打包,用于部署在服务器]编译程序要多且要慢。

android中JDK和SDK和API的区别
一、 SDK
sdk,就是软件开发包,是一个广义的概念,任何编程工具几乎都可以看成是SDK。单单说SDK,范围太大。如果是Android sdk,就可以理解是安卓机器的操作系统,类似Windows操作系统。没有Android sdk,就无法进行Android开发。简言之,jdk是sdk的一种。
二、SDK和API
SDK和API的区别SDK相当于开发集成工具环境,API就是数据接口。在SDK环境下调用API数据
实际上SDK包含了API的定义,SDK又不完完全全只包含API以及API的实现,它是一个软件工具包,它还有很多其他辅助性的功能。
通俗语言解释API前端调用后端数据的一个通道,就是我们俗说的接口,通过这个通道,可以访问到后端的数据,但是又无需调用源代码。
三、JDK
JDK:开发JAVA程序的开发包,JDK里面有JAVA的运行环境(JRE),包括client和server端,需要配置环境变量

c++与java的几个不同点
1—— c++有头文件 而JAVA中是import
a:Java里有package关键字的用法,在写的程序第一行使用package关键字来声明一个包。包就是一个文件夹,它将源代码文件(.java)、编译后的文件(.class)和其他的一些用到的文件有组织的放在一起编译器会在import导入的包里选择与类名对应的包,而#include则是编译器将其他文件的内容载入进来。
b:头文件就是包含在C++程序中的别人写好的一些东西,里面包含一些函数和一些特定的功能,比如一般使用的cout<< cin>> endl 等这些东西都包含在iostream里,sqrt,sin, cos等数学相关的函数都包含在cmath里。 在c++里有一个经典的命名:using namespace std;这行代码使得我们在使用cin、cout、endl……时不用加std::的前缀常常要用到的一些函数,或定义,或习惯,也可以自已做成一个头文件,在编程中引用,这样可以减少很大的不必要的重复工作量。
c语言里头的头文件里放的 还是源代码,而java引入的包是被编译过的*.class文件并且JAVA的包 绝对是以类为单位的…也就是个类是一个*.class文件多个类 组成一个包而C++是 可以一个头文件中放函数 放常量 放类
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200321235737828.png
2——代码格式
C/C++程序基本上是由n个函数组成,主函数调用其他函数实现所需功能。
Java程序是由n个类、m个方法组成,某个public类的主方法调用当前类的方法,或是调用其他类的公有(public)方法实现所需功能。Java的m个方法类似于C/C++的n个函数,只不过是将这m个方法放到n个类里,目录结构更清晰一些。
3——.录入输出
c++的录入输出靠输入流cin,输出流cout、cerr、clog实现,需要写#include。
Java语言里没有像c++那样一个函数就完成录入,它的录入使用了一些基础类,比如:
首先导包import java.util.Scanner;然后在方法内使用以下语句进行录入
4.——编译结果
a::c/c++编译的最终结果是一个程序生成一个exe文件。
b::Java编译结果是一个程序中有多少类就生成多少个与类名 相同的class文件。
5——指针问题
c/c++的引用,它跟java的引用完全不是一个东西,c/c++的引用是同一块内存的不同名字。而java的引用是指向一个对象,引用本身也占用了内存
a:首先,列举一下能对指针进行的一些常见操作:
指向一个对象,如 Person *p = new Person….;int *iv = new int….
对指针所指的对象进行操作:P->getAge();
b:指向一个对象,如Person p = new Person…
调用对象的方法,p.getAge();
指向另外一个对象,Person p1 = new Person…; p = p1;

弄懂 JRE、JDK、JVM 之间的区别与联系
JDK>JRE>JVM(开发工具包>运行环境>虚拟机)
JVM : (Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。
JRE : (Java Runtime Environment), Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JDK : (Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
显然,这三者的关系是:一层层的嵌套关系。JDK>JRE>JVM。
jdk 是我们的开发工具包,它集成了 jre ,因此我们在安装 jdk 的时候可以选择不再安装 jre 而直接使用 jdk 中的 jre 运行我们的 Java 程序。(但是大部分人都默认将两个都装上了)。但是如果你的电脑不是用来开发 Java 程序的,而仅仅是用来部署和运行 Java 程序的,那么完全可以不用安装 jdk,只需要安装 jre 即可。

硬件

计步器用的是安卓手机自带的传感器,目前所知有TYPE_STEP_DETECTOR和TYPE_STEP_COUNTER(会自动返回一个从自启动进程以来到目前为止的累计步数 貌似不用启用service),sevice是一种服务,保持进程在后台依然可以运行

扫描二维码关注公众号,回复: 10540806 查看本文章

Android SDK 中提供的面向软件的特性(生命周期)

activity生命周期介绍(为什么要有生命周期)
Activity生命周期并不仅仅在用户运行应用程序之后才开始生效,事实上它也影响着用户切出以及切回应用时得到的不同反馈。当我们开发一款应用时,首先需要牢记一点:用户会经常在执行过程中、在我们的应用与其它应用之间频繁切换。取决于用户的操作方式,同一款应用程序有时在前台运行、有时则在后台运行。大家必须保证自己的应用能够就会这类情况,并在此类切换过程中及时保存并恢复数据。(用户在一个界面上点击一下,然后程序在后台开启一个线程去加载数据,加载完成后通知界面显示数据,如果这些数据在退出App情况下也需要的话,还要把这些数据保存到本地文件中)
为了控制Activity处于不同状态下时应用程序的运行方式,例如当用户切出或者切回应用,大家可以选择多种处理方法。这类方法也就是Activity生命周期回调方法。Android系统会在我们的Activity进入某种特定状态后调用这些方法,从而通过一系列步骤确保我们的应用程序能够继续起效、不至于丢失数据而且在用户不与之交互时不会使用非必要性资源。每一种回调方法都会让我们的应用进入一种可能的状态。
如果大家之前曾经接触过Java应用程序的编程工作,那么应该已经发现Android应用程序的启动遵循另一种方式。与Java应用直接使用主方法不同,Android在启动后会首先执行主Activity类中的onCreate方法。请记住,我们已经在清单中将该类指定为主启动Activity。Activity会首先回调onCreate方法,相当于重复用户启动应用程序后的流程。这时候onCreate方法会使应用程序进入Created状态。
开发者指南当中通过示意图以直观方式介绍了生命周期、回调方法以及状态的概念。其中onResume方法负责提供Resumed状态,这时我们的应用程序可以接受用户的直接操作。其它各类回调方法都以onResume为核心,即将应用程序引导至Resumed状态或者从该状态脱离、启动该状态或者将其停止。
对于大部分应用程序来说,我们只需要使用一部分回调方法,但最起码要用到onCreate。虽然使用频率不高,但了解全部回调及状态的作用将帮助我们了解自己的应用程序在运行及停止运行时,Android系统会受到怎样的影响。一般情况下,大家需要保证用户能够在任何操作过程切换出去之后、都能顺利恢复到之前的运行状态;如果他们通过导航选择前进或者后退,应用则需保存全部必要数据并释放不必要占用的硬件资源。

基于场景解读Android四大组件
我们知道一个App里面最常见的交互流程是这样的:用户在一个界面上点击一下,然后程序在后台开启一个线程去加载数据,加载完成后通知界面显示数据,如果这些数据在退出App情况下也需要的话,还要把这些数据保存到本地文件中。我们把这个流程分解成下面四个步骤:
1、前台(界面展示);
2、后台(数据加载);
3、通信(前台和后台通信);
4、存储(数据存储);
到这里可能大家会明白我想说的是什么了。这里的每一步其实就对应了一个组件,Activity就代表了前台所要提供的功能,主要负责界面的展示和用户的交互。Service就代表了后台所要提供的功能,主要负责一些耗时工作如网络请求,文件读写的处理。Broadcast就代表了通信所要提供的功能,主要负责Activity和Service之间(当然也可以是Activity和Activity,Service和Service)的通信。ContentProvider就代表了存储所要提供的功能,主要负责数据在磁盘的读写。
这里也许会有很多人不认同我的说法,比方说后台任务不一定要用Service啊,我自己搞个线程池或者开个进程也可以,消息通信也不一定需要Broadcast,我自己用Handler或者AIDL也可以做,存储也不需要ContentProvider,我自己写一套文件读写框架也可以。如果你这样想,也是可以的,但是我这里说了,我只是基于使用场景来谈这四个组件,从App层面考虑,Android作为一个SDK,就需要提供给开发者在开发产品过程中实现一个基本功能所需的基本开发组件,而这些组件就是Activity,Service,Broadcast和ContentProvider,少一个不行,多一个没必要。当然这四大组件其实也是Android为了方便开发者使用而提供的,你可以不用,自己重写一套来实现我上面说的前台,后台,通信和存储这四步(现在很多App都是这么干的)。但终归是要实现这四大功能,一个都不能少。

Activity使用场景解读
这张图大家应该很熟悉了,这里我按使用场景来把它们分成三组:
onCreate和onDestroy
onStart、onRestart和onStop
onResume和onPause
第一组使用频率最高,为什么?因为它的使用场景是最多的,在一个App里面我们会经常需要打开(startActivity)和关闭(finish)一个页面。onCreate是Activity生命周期里面的第一步,当我们进入到这一步时就表示一个Activity实例对象(从Java的角度看)已经产生了,当我们New了一个Java对象之后,首先要做的肯定是对其进行初始化了,那么onCreate就是Android提供给开发者用来对Activity实例对象中的成员做初始化的。Tips:Android为了方便对Activity组件的管理以及开发者使用,对Activity做了封装,开发者不能直接new一个Activity对象(你也可以直接new,但是new出来的对象不会被Android管理,也就失去了界面的展示和交互的功能,跟普通Java对象无异).
在onCreate里面一般我们会做View的初始化操作,比如添加View(setContentView,addView等)和View中数据的填充(setText,setImage等),那么问题来了:为什么对View的初始化要放在这里,可不可以放到其他地方(onStart或者onResume)?答案是肯定的,但是我们不建议这么做,因为放在onCreate里面可以保证初始化操作只做一次,而放到其他地方可能会调用多次,当然你可以添加一个flag来标记是否已经做过初始化,这样就可以保证放在onStart或者onResume里面也只做一次初始化,但是这样不觉得多此一举么?既然onCreate已经帮我们实现了这么一个功能,为啥不用呢,当然如果你有特殊需求,另当别论。
还有就是在onCreate里面有个savedInstanceState参数,这个主要用于你的Activity在非正常情况下被销毁前帮你自动保存的一些数据,这些数据会在这个Activity被重新创建时用到,因此Android将这个参数放在了onCreate里面。注意,我这里说的是非正常情况销毁Activity,这种场景比较多,比如系统内存不够用,系统语言改变,屏幕方向改变等,如果你不清楚哪些是非正常情况,没关系,只要清楚正常情况就行了,其他的自然就都可以认为是非正常场景下的Activity销毁行为。那么正常情况是什么?用户主动意愿想要销毁Activity就是正常情况,这种场景很少,就两种:调用finish和带特殊启动模式的startActivity方法。那么对于非正常情况下的onCreate我们在里面又该如何使用这个savedInstanceState?那么就要搞清楚savedInstanceState会保存到哪些数据,有两种:系统帮你自动保存的和你自己保存的。系统只会保存它认为有必要保存的(比方说EditText里面的内容,CheckBox的Check状态,Fragment实例等),但是很多童鞋不知道Activity会自动保存其中的Fragment实例,onCreate写成这样子:
在这里插入图片描述onStart、onRestart和onStop
说实话这三个回调接口在实际使用场景中并不多,对onStart、onRestart和onStop的使用可以从是否可见这点来找到它的正确使用姿势。这里举几个常用的场景:
对数据的时效性要求较高。以新闻类App为例:Activity A代表新闻列表,点击列表中的一个Item进入到Activity B新闻详情,在从B返回到A的时候为了保证用户能看到最新的新闻,就需要从服务器拉取最新的新闻列表数据并填充到Activity A,那么这个工作就可以放在onStart里面,当然你也可以放在onRestart里面,但是activity首次加载启动的时候不会调用onRestart,所以也就不会去拉取新闻列表数据。
需要显示动画效果。有些activity需要显示一些动画来帮助提升用户体验,但是当我们从该页面进入到一个新页面时,由于该页面已经不可见了,所以就可以把当前页面中的动画给关掉以节省系统资源,而这个工作就可以放在onStop中进行。
onResume和onPause
这两个接口使用的频率比上一组要高,对onResume和onPause的使用可以从可以从是否获得焦点(焦点即代表是是否可交互)这点来找到它的正确使用姿势,这里也举几个常见场景:
结束占用CPU的动画或者其他正在运行任务,这种在使用地图SDK的时候比较常见:

Service使用场景解读
Service是Android提供给开发者的一个组件,主要用于后台一些耗时任务的处理。其实Android系统中已经存在了很多这样在后台执行一些特定任务的系统级Service,比方说与我们开发中打交道最多的ActivityManager,WindowManager,PackageManager和InputManager等等。
![![在这里插入图片描述](https://img-blog.csdnimg.cn/20200322035230310.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bnhpdTk4ODYyMg==,size_16,color_FFFFFF,t_70](https://img-blog.csdnimg.cn/20200322035301538.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l1bnhpdTk4ODYyMg==,size_16,color_FFFFFF,t_70
这些方法能够让我们的应用程序在可能的状态之间进行切换,而且某些情况下切换速度会很快。通常来说,大家可以认为自己的应用程序始终处于resumed、paused或者stopped这三种状态之下,因为其它状态都是暂时性的。从图中可以看出Service的生命周期会根据启动方式的不同有不同的生命周期回调。其实startService和bindService的区别就是该service是否可以和启动它的组件(比如activity)通信,因为bindService可以拿到Service的binder,binder就是用来实现IPC(进程间通信)的嘛。下面我们具体分析下每个生命周期回调:
onCreate
该接口是在Service实例被创建时调用,这里的Service实例跟Activity实例不一样,我们知道Activity实例根据不同的启动模式可以有一个或者多个实例,但是,Service虽然也有两种启动方式,在整个系统中却只会有一个Service实例。为什么呢?换个角度看,这就好比PC端的C/S模式,使用一个服务端去处理多个客户端的请求,这里就对应一个Service去处理来自多个Activity的请求嘛,没必要搞多个,浪费资源,而且你会发现系统级Service其实也都只有一个实例。那么在onCreate里面我们可以做些什么呢?当然是初始化,比如创建数据缓存,线程池等等。Android系统给我们提供了一个IntentService,我们可以参考它的实现方式来做一些初始化操作,IntentService的onCreate源码如下: 这里为什么要创建新的线程或者线程池呢?因为Service默认是在主线程中执行的,所以我不建议你把一个后台任务放在Service中的主线程执行,因为那样就失去了Service存在的初衷,还不如直接放在Activity里面做,除非你想要提升App进程的优先级,防止App退到后台被杀掉。
在这里插入图片描述onStart
该接口是在调用startService方法时调用的,我们的后台任务一般都会放在这里执行,你可以通过intent获取startService方法传递的参数,这里依然以IntentService为例看下它的实现方式:
在这里插入图片描述onBind
该方法是在调用bindService方法时调用,如果使用bindService方式来启动服务的话,一般发生在Activity需要与Service进行通信的场景(比如说音乐播放器app里面就会用到),而Android的IPC主要是通过binder来实现的(也可以通过socket,在系统服务用的比较多),所以这里方法的返回值就需要一个binder实例。这里简单说下binder的实现机制(后续讲Broadcast的时候我们在具体分析Android的IPC机制具体实现),其实就是一套PC上的C/S模式,用户通过bindService接口获取到Service的代理,然后通过这个代理来跟Service通信。我们这里用一段代码来详细说明下:
这里的代理分两种:本地代理和远程代理,它们是按照service和activity是否在同一个进程中来区分的(这里仅以activity和service通信为例来说明,其他场景原理类似),如果是在同一进程,那么这个代理对象mServiceProxy其实就是mService对象。而当它们不在同一个进程中时,mServiceProxy和mService就属于不同进程空间中的对象,由于不同进程之间的数据不能直接访问,所以这个时候binder driver就来充当一个中间桥梁的作用,来完成参数和返回结果等数据的传递(其实也就是在Linux内核空间开辟了一段共享内存),从而实现通信的目的。当然为了方便开发者使用binder,Android对binder的使用进行了一定的封装,提供了一个AIDL。通过AIDL我们就只需关心service提供的功能接口,而不用去关心这些接口调用的具体细节。所以从这里也可以看出,对于一个好的产品,不管它的用户群是普通用户还是程序员,使用的便捷性都是一个很重要的指标。就好比现在市面上很多做SDK的,往往那些接口简单,文档清晰的SDK,用的人也会多一些。
在这里插入图片描述
onUnbind
该方法是在调用unbindService方法时调用,一般发生在activity中需要断开与service的连接的场景。注意该接口有个返回值,默认为false。如果你想要在onRebind里面做一些事情的话,那么这里需要返回true。
onDestroy
该方法会在Service销毁时调用,一般在这里我们会释放一些在onCreate中进行初始化时所申请的资源,可以参考IntentService的实现方式:
在这里插入图片描述Service使用场景
为了满足开发者处理后台任务的需要,Android提供了Service这个组件,同时为了方便开发者使用Service,又封装了一个IntentService。当然,现在很多App在处理后台任务的时候并没有优先使用Service,而是自己实现了一套线程池机制或者使用Android提供的AsyncTask来执行后台任务,这里我们来分析下他们各自的优劣:
Service的优点是系统原生支持,使用方便;创建进程方便;可以提供给系统内其他App使用;优先级高,当App退到后台后不宜被杀死。缺点是由于启动Service涉及到多次IPC,运行效率不高,而且受限于系统接口,使用不够灵活。
线程池的优点是运行效率高,配置和使用灵活。缺点是多进程实现不方便, 由于Android实现了一套进程托管机制,我们不能直接创建一个新的进程,而只能通过四大组件的形式创建新的进程。
基于以上分析,我们可以看出,一般普通的异步任务,比如网络请求,数据库或者文件相关操作,我们都会使用线程池的方式来做,因为这样使用的系统开销小,运行效率高,而且随着业务逻辑的复杂度增加,扩展性也更强。然而,对于一些特殊场景,比如进程保活,使用第三方SDK服务比如地图,IM等,就需要使用Service来实现,因为这些服务一般与App主进程隔离开,需要运行在新进程中以防止App主进程发生异常崩溃时,牵连第三方服务也挂掉。

如何把传感器的数据传入app

这里使用了android SDK里的一个sensor类

  • 大致思路

    用SensorManager获得该传感器(用sensor_service返回一个sensorManager对象),然后为传感器建立一个SensorEventListener(传感器事件监听器),这个监听器中包含两种需要实现的方法(nAccuracyChanged ,onSensorChanged ),方法规定了当传感器值发生变化时,监听器监听到该事件于是采取操作,返回当前传感器的值

  • 补充下传感器的工作原理: 传感机是靠感知手机振动来实现计步的,电子计步器主要由震动传感器和电子计数器组成。人在步行时重心都要有一点上下移动。 电子计步器的工作核心就是震动传感器,它里面有一个机械的震子,运动时会产生上下震动,机器通过收集震子运动的频率来计算数值 。

数据库

Android 五种数据存储的方式分别为:
作为一个完整的应用程序,数据存储操作是必不可少的。因此,Android系统一共提供了四种数据存储方式。分别是:SharePreference、文件存储、SQLite、 Content Provider。对这几种方式的不同和应用场景整理如下。
第一种: 使用SharedPreferences存储数据
适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口令密码等
  核心原理:保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data//shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences本身是一 个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下:  Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。
Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。
Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写
SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。
第二种: 文件存储数据
  可以在设备本身的存储设备或者外接的存储设备中创建用于保存数据的文件。同样在默认的状态下,文件是不能在不同的程序间共享。
  写文件:调用Context.openFileOutput()方法根据指定的路径和文件名来创建文件,这个方法会返回一个FileOutputStream对象。
  读取文件:调用Context.openFileInput()方法通过制定的路径和文件名来返回一个标准的Java FileInputStream对象。
第三种:SQLite存储数据
  SQLite Database数据库。Android对数据库的支持很好,它本身集成了SQLite数据库,每个应用都可以方便的使用它,或者更确切的说,Android完全依赖于SQLite数据库,它所有的系统数据和用到的结构化数据都存储在数据库中。 它具有以下优点: a. 效率出众,这是无可否认的 b. 十分适合存储结构化数据 c. 方便在不同的Activity,甚至不同的应用之间传递数据。第四种:ContentProvider
  Android系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个ContentProvider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享时,就需要使用ContentProvider为这些数据定义一个URI,然后其他的应用程序就通过Content Provider传入这个URI来对数据进行操作。
  总结一下,文件适用于存储一些简单的文本数据或者二进制数据,SharedPreferences适用于存储一些键值对,而数据库则适用于那些复杂的关系型数据。

SharedPreferences类介绍
Android平台给我们提供了一个SharedPreferences类(是一种方法,就像content provider一样是一种方法,具体是怎么存储到硬件上的我们不用关心,只要知道是以xml文件存储的就行了),它是一个轻量级的存储辅助类,特别适合用于保存软件配置参数和应用的一些常用配置。 例如,一些默认欢迎语、登录的用户名和密码等比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。SharedPreferences 可以用来进行数据的共享,包括应用程序之间,或者同一个应用程序中的不同组件。比如两个activity除了通过Intent传
使用SharedPreferences保存数据, 其背后是以“键-值”对的方式用xml文件存放数据,文件存放在/data/data//shared_prefs目录下。提示最终是以xml方式来保存,整体效率来看不是特别的高,对于常规的轻量级而言比SQLite要好不少
如何利用xml存储数据的
具体编程实现

ContentProvider使用场景解读
ContentProvider在整个Android系统中扮演了数据管理的角色,负责整个Android系统中App数据的访问和各App之间的数据共享,ContentProvider提供了一些通用的接口来实现对底层数据(其实是数据库中的表结构数据)进行操作。
ContentProvider是什么?
ContentProvider是Android提供给上层的一个组件,主要用于实现数据访问的统一管理和数据共享。这里的数据管理是通过定义统一的访问接口来完成,如增删改查。同时,它采用了类似Internet的URL机制,将数据以URI的形式来标识,这样其他App就可以采用一套标准的URI规范来访问同一处数据,而不用关心具体的实现细节。我们知道在Android系统中可能会涉及到一个App的数据被其他App使用的情况,比如通讯录,日历,短信等,这时就需要一套能实现数据共享的机制,这里的ContentProvider就可以提供该功能,其底层使用了binder来完成App进程之间的通信,同时使用匿名共享内存来作为共享数据的载体。当然为了保证数据访问的安全性,ContentProvider还对每处的数据URI增加了权限管理机制,以控制该数据的访问者及访问方式。
最后再说下为何ContentProvider在我们平时开发App中使用的不多?其实,虽然ContentProvider具有数据管理和数据共享的功能,但是多半的优势还是集中在数据共享上,在数据共享的前提下,这个数据管理的优势也才能更加明显。像一些系统内置应用,联系人,日历和短信,就比较适合使用ContentProvider,因为他们经常需要给其他App提供数据。而对于像普通App,一般出于安全原因,不会把数据提供给第三方App使用,而在App内部访问数据库的话,完全可以自己实现一套数据库访问框架,因为ContentProvider为了屏蔽数据库的访问细节,实质上是在其基础上再封装了一层接口而已,而对于App内部的数据库访问来说,没有这个必要

用service实现计步器的后台运行

这个问题相当于为什么当计步器转入后台程序的时候仍然可以实现计步的功能,这就引入了我本段要讲的组件service。

  • 讲sevice之前先讲一下何为后台
    安卓软件所处的一种生命周期Activity一般有四种状态:
    (1)running:当Activity位于栈顶时,此时正好处于屏幕最前方,此时处于运行状态;
    (2)paused:当Activity失去了焦点但仍然对用于可见(如栈顶的Activity是透明的或者栈顶Activity并不是铺满整个手机屏幕) ;
    (3)stoped:当Activity被其他Activity完全遮挡,此时此Activity对用户不可见
    (4)destoryed:当Activity由于人为或系统原因(如低内存等)被销毁 ;
    后台即paused和stop状态。

  • 具体应用
    一个service是一段长生命周期的,没有用户界面的程序,一个例子就是手机播放音乐时用户可以进行其他应用的活动,或者闹钟关机之后仍然可以响。对service其实就是在主页面基础上(在oncreat中)写一个intent,然后可以把service定义到onclick中(用intent转换),service也有生命周期例如oncreat,onstart,

  • 支付宝和微信的计步原理
    -

  • 是怎么实现交互的
    安卓需要用到一个组件叫activity,一个activity提供一个屏幕,用户可以用来交互已完成某种任务,例如点击、拨号拍照。由于安卓是事件驱动的,因此当你做操作的时候会对应一系列处理,最典型的就是点击事件的设置,为监听事件设置一个监听器,当监听器监听到你的动作就会跳转到该动作触发的程序,这样就完成了一次交互操作。 监听器概念在安卓中非常重要,在上文中提到获取传感器数据时也用到了一个sensorlistener(是监听传感器的值是否发生改变)

  • 补充事件驱动的定义:

    首先我们来给事件驱动编程下一个定义。事件驱动编程是一种编程范式,程序的执行流程是由动作(actions,例如用户交互,其他线程发送的消息等等)触发的事件(event)决定的。在这个意义上,Android是部分事件驱动:我们都知道的onClick监听器或者Activity的生命周期,都是应用中由动作触发的事件。我为什么说它不是纯粹的事件驱动系统呢?默认情况下,每个事件被绑定在特定的controller上面,因此很难在其他地方使用该事件(例如onClick事件是定义为View服务的,因此它的使用范围很有限)。

    是如何获得时间的

    由于安卓中system类中提供获取时间的方法(System.currentTimeMillis()),因此我们要做的就是开启一个线程,无限循环该线程,在线程中用handler的message的通信机制,每隔一秒就会发出一个message,然后就可以主线程中处理消息并更新时间,在通过xml的设计显示到界面上就行了。

计步器的各类性能

准确率方面
android机型众多,传感器的灵敏度不一,因此会出现各种计步数不同的现象
传感器的选择
由于android4.4 就支持stepcount了 因此可以直接接受返回值,省去了对于步数检测的一系列算法
实现隔天清零以及查看历史数据的操作
//emmm这个功能以后再学习吧
隔天清零 参考该篇博文
感觉这个博主的代码很易懂,附传送门~
这个是关于计步器的一篇论文

  • 计步器的问题

安卓的计步传感器,重启数据清零,跨天数据不会清零,所以当天的数据需要自己计算.当天的最后一次步数 - 当天的第一次步数 = 当天的步数, 还要考虑重启传感器清零的情况."还有些手机杀掉进程可以获取数据,但是隔天需要重新开启进程,不然不会计步。"这个就是第一次打开注册了读取到当时的值了
首先抛出问题android4.4之后提供了两个传感器STEP DETECTOR 以及 STEP COUNTER,但是这两个传感器虽然可以很方便的提供给我们步数,但返回的步数是从开机以来的累计步数,隔天数据无法实现清零 ,并且关机之后无法实现
先来看下我们需要解决的点有:

1、步数从开机之后不断累加,关机之后便清零,步数 不能隔天清零

2、不能查看历史数据

数据的存储

有关android四大组件引用于https://www.jianshu.com/p/9612c33686b9

https://blog.csdn.net/chaoyu168/article/details/52997036Android SDK上手指南:Activity与生命周期

发布了142 篇原创文章 · 获赞 0 · 访问量 2618

猜你喜欢

转载自blog.csdn.net/yunxiu988622/article/details/104898651
今日推荐