Email5.0 代码结构

Email5.0 代码结构

1核心接口IEmailService

IEmailServiceEmail的核心接口。定义了Email的基本功能。如发送邮件(sendmail,下载附件(loadAttachment,同步(sync)搜索邮件(searchMessages)等。EmailServiceStub实现了IEmailService接口。主要实现POP3IMAP邮箱共同的一些方法。EmailServiceStub为抽象类,它有两个子类。这两个子类分别是POP3邮箱和IMAP邮箱对该接口的实现。这两个子类针对POP3IMAP协议的不同重写了父类的某些方法。如POP3协议不支持单独的下载附件,在POP3的子类中重写了父类的loadAttachment。这两个子类分别为Pop3ServiceImapService的匿名内部类。Exchange协议的IEmailService实现位于EasService的匿名内部类中。

1.1主要接口功能介绍

sendmail 发送邮件。

POP3/IMAP邮箱使用SMTP协议发送邮件,sendmail功能在EmailServiceStub中实现。

Exchange邮箱通过HTTP协议发送邮件,邮件内容为XML格式。通过POST方法上传到服务器。Exchange邮箱并没有实现sendmail,而是由syncOutbox函数实现发送邮件的功能。

loadAttachment下载附件。

POP3协议不支持单独的下载附件,当下载附件时要把整个邮件全部下载下来。IMAPExchange协议可以实现单独的下载附件功能。

 

searchMessages 搜索邮件

searchMessages不是搜索本地数据库中的邮件,而是搜索邮件服务器中的邮件内容。Email客户端向服务器发出搜索命令,服务器把包含关键字的邮件返回给客户端。POP3协议没有搜索命令,因此POP3邮箱没有搜索功能。

sync 同步

同步功能主要同步三项内容

1、同步服务器的文件夹列表

2、同步outbox中的邮件,其实就是发送outbox中的邮件。

3、同步inbox中的邮件,最主要的同步操作。

1.2 C/S结构

Exchange位于独立的模块中(不知道为什么把Exchange独立出来,一种可能原因是日历和联系人模块也要使用Exchange的功能)。EmailExchange属于不同的进程,Exchange只负责功能实现,没有显示界面,邮件内容在Email模块显示,EmailExchange通过Binder机制进行通信。为了和Exchange的代码保持一致POP3IMAP邮箱代码也采用了C/S结构(在4.4之前Email不是这种结构)。采用Binder通信,代码分为Proxyclient)和StubService)两部分。只不过POP3IMAPService位于Email进程中,不是跨进程的通信。ExchangeService位于Exchange进程中,是跨进程的通信。

IEmailService接口在代理端也有相应的实现,实现类为EmailServiceProxy(代理类只是把请求转交给Stub)。上层代码只和EmailServiceProxy交互,EmailServiceProxy根据不同

的账户类型绑定(bind)不同的实现类。这种结构最大的好处是上层代码只需要针对IEmailService接口编程,不用关心三种协议的差别。

当需要执行一项邮件操作时,就创建一个EmailServiceProxy对象。然后调用相应的函数执行。例如下载附件时执行如下语句:

new EmailServiceProxy(context, class).loadAttachment(attachmentId, callback)

根据参数class绑定不同的服务,执行不同协议的下载代码。POP邮箱绑定Pop3ServiceIMAP邮箱绑定ImapServiceExchange邮箱绑定EasServicePop3ServiceImapServiceEasService会在onbind函数中返回IEmailService接口的实现。EmailServiceProxy会创建一个异步任务,在异步任务中请求服务端执行下载附件操作。附件下载结束后代理端断开和服务器的连接。因此一个EmailServiceProxy对象只能执行一次邮件操作。

2同步框架

4.4 平台开始,Email采用了Android的同步框架实现邮件的同步功能。以POP3邮箱为例,说明同步框架同步邮件的过程。

2.1同步框架介绍

为了使框架层能够调用Email的同步代码,Email必须提供一个 Bound Service类。该类在onbind函数中返回给框架层一个实现了同步操作的binder引用。当需要同步时同步框架通过该引用远程调用onPerformSync函数执行同步操作。该binder是连接框架层和我们应用程序的关键。那么如何创建该Bind对象?

       首先该对象必须是一个Bind对象,而且必须实现了onPerformSync函数。Google提供了AbstractThreadedSyncAdapter类,我们做的工作只需要继承AbstractThreadedSyncAdapter重写onPerformSync

POP3邮箱中创建该binder的代码如下:

private static class SyncAdapterImpl extends AbstractThreadedSyncAdapter {

        public SyncAdapterImpl(Context context) {

            super(context, true /* autoInitialize */);

        }

        @Override

        public void onPerformSync(android.accounts.Account account, Bundle extras,

                String authority, ContentProviderClient provider, SyncResult syncResult) {

            PopImapSyncAdapterService.performSync(getContext(), account, extras, provider,

                    syncResult);

        }

    }

一般在Bound ServiceonCreate函数中创建该binder的引用。在onBinder函数中调用getSyncAdapterBinder返回binderBound ServiceonCreateonBind 函数如下:

   @Override

    public void onCreate() {

        super.onCreate();

        mSyncAdapter = new SyncAdapterImpl(getApplicationContext());

    }

    @Override

    public IBinder onBind(Intent intent) {

        return mSyncAdapter.getSyncAdapterBinder();

    }

 

bound Service除了需要返回一个特殊的binder之外,在声明时还有一些特殊。必须在intent-filter中加入android.content.SyncAdapter action,这样框架层可以发出intent绑定该服务。还需要在meta-data中加入元数据文件。该文件位于/res/xml/目录中,文件描述了我们要同步的账户类型,应用使用的 content providerauthority,同步控制等详见官方文档。

adt-bundle-windows-x86-20140702\sdk\docs\training\sync-adapters\index.html

Email中负责POP3邮箱同步的bound Service声明如下:

<service

    android:name="com.android.email.service.Pop3SyncAdapterService"

        android:exported="true">

            <intent-filter>

                <action

                    android:name="android.content.SyncAdapter" />

            </intent-filter>

            <meta-data android:name="android.content.SyncAdapter"

                       android:resource="@xml/syncadapter_pop3" />

 </service>

元数据syncadapter_pop3的内容如下:

<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"

    android:contentAuthority="@string/authority_email_provider"

    android:accountType="@string/account_manager_type_pop3"

    android:supportsUploading="true"

    android:allowParallelSyncs="true"

/>

 

其中allowParallelSyncs表示同一类型的账户可以创建多个,并发的执行同步操作。例如可以创建两个Pop3类型的邮箱,这两个邮箱可以同时执行同步操作。

android:supportsUploading设置是否必须notifyChange通知才能同步

defaults to true and if true an upload-only sync will be requested for all syncadapters associated with an authority whenever that authority's content provider does a notifyChange(android.net.Uri, android.database.ContentObserver, boolean) with syncToNetwork set to true.

       如果supportsUploading设置为true,当执行ContentResolver. notifyChange时,会执行同步操作。POP3/IMAP邮箱supportsUploading=true。之前对该选项不了解,造成了很大的麻烦。当执行了邮件加星操作时,会立刻同步到服务器。当时一直到不到同步代码。后来发现是执行ContentResolver. notifyChange时执行的同步。Exchange邮箱supportsUploading=false

当更改了邮件状态时必须手动请求框架执行同步。

       Email中用于POP3邮箱的同步服务为Pop3SyncAdapterServiceIMAP邮箱为LegacyImapSyncAdapterServiceExchange邮箱为EmailSyncAdapterServiceExchange邮箱还可以同步联系人和日历,同步服务分别为ContactsSyncAdapterServiceCalendarSyncAdapterService

2.2使用同步框架执行同步

Email中执行同步操作有两种情况,一种是手动刷新执行同步,一种时周期性的执行同步。使用同步框架可以非常简单的实现这两种操作。手动同步时只需执行 ContentResolver.requestSync(),框架层就会回调onPerformSync函数执行同步操作。

周期性同步时调用ContentResolver.addPeriodicSync(),在参数中指定同步周期,就可以周期性的执行同步操作。在手动同步时可以指定

       使用同步框架执行同步操作有很多好处,首先我们编写同步代码更简单,只需要提供接口让框架层调用。之前Email周期性同步是使用AlarmManager实现的,代码比同步框架要复杂很多。其次同步框架在执行同步是会检查网络链接情况,如果没有网络链接则不会执行同步操作。再次同步框架还提供了用户验证机制。

3协议层接口(Exchange 部分)

Exchange协议主要通过HTTP协议与服务器交互。发送的命令和返回的结果都是XML格式。

执行Exchange命令其实就是向服务器发送POST请求并解析响应结果。命令中包含很多参数,这些参数都放在xml文件的对应标签中。Exchange协议对每个命令的作用和包含的参数都有详细的描述,具体内容可以参考微软的文档

https://msdn.microsoft.com/en-us/library/ee200913(v=exchg.80).aspx

执行Exchange命令通常就是发送POST请求,处理常见错误,解析返回结果。

ExchangeEasOperation类中的performOperation方法定义这一套流程performOperation是一个模板方法,调用了很多虚函数实现发送请求,解析结果的操作。EasOperation有很多子类,每一个类对应一个Exchange操作。子类只需要重写一些虚函数就可以实现定义的操作。

EasMoveItems  实现邮件位置移动

EasLoadAttachment 实现下载附件功能

EasFullSyncOperation 实现整个邮箱的同步功能

EasFolderSync 同步文件夹列表。

EasOutboxSync 实现发送邮件功能

EasSearch  实现搜索邮件功能

EasSync 实现某个文件夹同步邮件功能(upload

EasSyncBase实现某个文件夹同步邮件功能(download

EasSync EasSyncBase共同实现文件夹的同步

EasFullSyncOperation类实现的功能并不对应具体的某个Exchange命令,而是在performOperation调用其他的类实现整个邮箱的同步。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值