- 浏览: 1067998 次
- 性别:
- 来自: 南昌
文章分类
- 全部博客 (276)
- 生活 (1)
- 代码之美 (22)
- Media (7)
- Android Widget (3)
- Android Intent (1)
- Android Activity (4)
- UI event handle--UI事件处理机制 (2)
- Java基础知识 (12)
- android Databases (5)
- Android 系统知识 (70)
- 平常遇到的问题与解决方法 (38)
- Android TextView/EditView (2)
- Thinking Java (1)
- android webkit (6)
- JSON (1)
- XML (4)
- HTTP (1)
- Google Weather API (1)
- android 2.3 NFC (10)
- android app (20)
- android framework (7)
- C++ (2)
- android System (5)
- Pthread (1)
- Wifi (8)
- Unix/Linux C (8)
- Android 4.0 (1)
- Mail (1)
- Smack 源码学习 (4)
- iOS (4)
- Android (1)
- git (1)
- Gallery3d (2)
- React-Natice (1)
最新评论
-
dd18349182956:
你是用的smack哪个版本?我用的smack4.1.3和sma ...
关于socket长连接的心跳包 -
xukaiyin:
全英文
getApplicationContext()与this,getBaseContext() -
裂风矢:
...
<category android:name="android.intent.category.DEFAULT" /> 惹的祸 -
xanthodont:
mark一下
XMPP——Smack -
Evilover3:
mark一下,学习了
XMPP——Smack
当用户在Setting中清除了Email的data,再返回到Email进行新建邮件就会一直显示“waiting for sync”.从字面的意思就是要进行同步,我跑到Setting-->Account中手动同步了账号,再新建邮件,发现问题仍一直存在。
1.导出Email APP的数据查看Account tables的数据发现,发生问题和正常时数据是一致的
2.通过搜索“waiting for sync”定位到显示该UI的是在ComposeActivity.java中
3.接着分析何时会调用showWaitFragment,发现是当Account的状态处于
INITIAL_SYNC_NEEDED或者ACCOUNT_INITIALIZATION_REQUIRED
4.接着分析syncStatus的值的来源
通过加log打印发现account最后SYNC_STATUS都会修改为NO_SYNC,为何在ComposeActivity查询出来的仍旧是INITIAL_SYNC_NEEDED
5.返回ComposeActivity分析Account的加载过程
首先是checkValidAccounts中
调用AccountUtils.getAccounts查询出Account
此处调用查询的uri是content://com.android.mail.accountcache/它对应的ContentProvider是UnifiedAccountCacheProvider,真正实现的是MailAppProvider
6.分析发现MailAppProvider会将从EmailProvider查询到结果缓存到SharePreference和mAccountCache中,当query只是从mAccountCache获取,而MailAppProvider会在onCreate的时候就会从EmailProvider中获取结果,并且此时account并没有同步完成导致缓存的结果的syncstatus是INITIAL_SYNC_NEEDED
7.那问题点找到了,该如何解决呢?如何让ComposeActivity获取到最新的状态。又返回到了checkValidAccounts中,发现当isAccountReady 返回false时,会重新getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);说明会进行二次查询,可是此处查询的仍然是MailAppProvider缓存的结果,而非EmailProvider中的
从上面的code可以看到uri和projection与AccountUtils.getAccounts一样,所以数据当然一样啊,仍然是INITIAL_SYNC_NEEDED。
8.那居然google原本就设计了第二次查询,那最简单的解决方法就是在二次查询的时候将uri指向EmailProvider这样,问题就解决了。
此处指向的uri为content://com.android.email.provider/uiaccts
9.测试,问题解决。Google也有出错的时候,只要是人写的code就会有漏洞!
1.导出Email APP的数据查看Account tables的数据发现,发生问题和正常时数据是一致的
2.通过搜索“waiting for sync”定位到显示该UI的是在ComposeActivity.java中
private void showWaitFragment(Account account) { WaitFragment fragment = getWaitFragment(); if (fragment != null) { fragment.updateAccount(account); } else { findViewById(R.id.wait).setVisibility(View.VISIBLE); replaceFragment(WaitFragment.newInstance(account, false /* expectingMessages */), FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT); } }
3.接着分析何时会调用showWaitFragment,发现是当Account的状态处于
INITIAL_SYNC_NEEDED或者ACCOUNT_INITIALIZATION_REQUIRED
public boolean isAccountReady() { return !isAccountInitializationRequired() && !isAccountSyncRequired(); } public boolean isAccountSyncRequired() { return (syncStatus & SyncStatus.INITIAL_SYNC_NEEDED) == SyncStatus.INITIAL_SYNC_NEEDED; } public boolean isAccountInitializationRequired() { return (syncStatus & SyncStatus.ACCOUNT_INITIALIZATION_REQUIRED) == SyncStatus.ACCOUNT_INITIALIZATION_REQUIRED; }
4.接着分析syncStatus的值的来源
private String genQueryAccount(String[] uiProjection, String id) { .... if (projectionColumns.contains(UIProvider.AccountColumns.SYNC_STATUS)) { if (inboxMailboxId != Mailbox.NO_MAILBOX) { values.put(UIProvider.AccountColumns.SYNC_STATUS, UIProvider.SyncStatus.NO_SYNC); } else { values.put(UIProvider.AccountColumns.SYNC_STATUS, UIProvider.SyncStatus.INITIAL_SYNC_NEEDED); } } ...
通过加log打印发现account最后SYNC_STATUS都会修改为NO_SYNC,为何在ComposeActivity查询出来的仍旧是INITIAL_SYNC_NEEDED
5.返回ComposeActivity分析Account的加载过程
首先是checkValidAccounts中
private void checkValidAccounts() { final Account[] allAccounts = AccountUtils.getAccounts(this); if (allAccounts == null || allAccounts.length == 0) { final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this); if (noAccountIntent != null) { mAccounts = null; startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT); } } else { // If none of the accounts are syncing, setup a watcher. boolean anySyncing = false; for (Account a : allAccounts) { if (a.isAccountReady()) { anySyncing = true; break; } } if (!anySyncing) { // There are accounts, but none are sync'd, which is just like having no accounts. mAccounts = null; getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this); return; } mAccounts = AccountUtils.getSyncingAccounts(this); finishCreate(); } }
调用AccountUtils.getAccounts查询出Account
public static Account[] getAccounts(Context context) { final ContentResolver resolver = context.getContentResolver(); Cursor accountsCursor = null; final List<Account> accounts = Lists.newArrayList(); try { accountsCursor = resolver.query(MailAppProvider.getAccountsUri(), UIProvider.ACCOUNTS_PROJECTION, null, null, null); if (accountsCursor != null) { while (accountsCursor.moveToNext()) { accounts.add(Account.builder().buildFrom(accountsCursor)); } } } finally { if (accountsCursor != null) { accountsCursor.close(); } } return accounts.toArray(new Account[accounts.size()]); } }
此处调用查询的uri是content://com.android.mail.accountcache/它对应的ContentProvider是UnifiedAccountCacheProvider,真正实现的是MailAppProvider
6.分析发现MailAppProvider会将从EmailProvider查询到结果缓存到SharePreference和mAccountCache中,当query只是从mAccountCache获取,而MailAppProvider会在onCreate的时候就会从EmailProvider中获取结果,并且此时account并没有同步完成导致缓存的结果的syncstatus是INITIAL_SYNC_NEEDED
7.那问题点找到了,该如何解决呢?如何让ComposeActivity获取到最新的状态。又返回到了checkValidAccounts中,发现当isAccountReady 返回false时,会重新getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this);说明会进行二次查询,可是此处查询的仍然是MailAppProvider缓存的结果,而非EmailProvider中的
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { switch (id) { case INIT_DRAFT_USING_REFERENCE_MESSAGE: return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, null, null); case REFERENCE_MESSAGE_LOADER: return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, null, null); case LOADER_ACCOUNT_CURSOR: return new CursorLoader(this, MailAppProvider.getAccountsUri(), UIProvider.ACCOUNTS_PROJECTION, null, null, null); } return null; }
从上面的code可以看到uri和projection与AccountUtils.getAccounts一样,所以数据当然一样啊,仍然是INITIAL_SYNC_NEEDED。
8.那居然google原本就设计了第二次查询,那最简单的解决方法就是在二次查询的时候将uri指向EmailProvider这样,问题就解决了。
@Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { switch (id) { case INIT_DRAFT_USING_REFERENCE_MESSAGE: return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, null, null); case REFERENCE_MESSAGE_LOADER: return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, null, null); case LOADER_ACCOUNT_CURSOR: final String[] accountQueryUris = this.getResources().getStringArray(R.array.account_providers); return new CursorLoader(this, Uri.parse(accountQueryUris[0]), UIProvider.ACCOUNTS_PROJECTION, null, null, null); } return null; }
此处指向的uri为content://com.android.email.provider/uiaccts
9.测试,问题解决。Google也有出错的时候,只要是人写的code就会有漏洞!
发表评论
-
Android Webview加载www.youtube.com的问题
2019-04-25 10:36 996Android Webview加载www.youtube.co ... -
EditText键盘删除字符的原理
2018-10-29 19:21 1255转https://blog.csdn.net/tankai19 ... -
Background execution not allowed
2018-10-22 19:02 362411-05 10:08:18.058 673 736 ... -
failed to set system property
2018-10-17 09:21 4419在App的mk文件设置了LOCAL_CERTIFICATE : ... -
CtsDeqpTestCases fail
2018-07-27 09:44 3029Suite / Plan:VTS / cts-on-gsi ... -
在DocumentUI中的Recent(最近)列表无法显示图片的缩略图
2018-06-12 18:23 942今天客户提了一个bug说在短信添加附件,界面无法显示缩略图。接 ... -
在任务栏中清除掉播放器的进程,状态栏仍有音乐播放器状态,且音乐仍在后台播放
2018-06-05 11:28 1666在任务栏中清除掉播放器的进程,状态栏仍有音乐播放器状态,且音乐 ... -
junit.framework.AssertionFailedError: Failed to get achievable frame rates for O
2018-05-25 15:41 2363之前对于CTS测试的失败case接触不多,组长突然转了这样一个 ... -
Android 模拟各种事件的方法
2018-05-17 16:30 1535有时候没有对应的硬件设备,那我们就得通过某种方式来模拟。比如模 ... -
javax.net.ssl.SSLHandshakeException: Unacceptable certificate: CN=GeoTrust SSL C
2018-01-30 16:48 3813最近从Android N升级到Android O,发现163的 ... -
Email中附件名称中包含中文字符显示乱码
2017-11-28 17:09 1623Email中附件名称中包含中文字符显示乱码是因为附件虽包含了中 ... -
不能再通过createPackageContext来访问另外一个应用的资源(Sharepreference)
2017-11-14 17:22 1465以前我们可以通过createPackageContext来访问 ... -
当Email未设置账户时,通过ACTION_SENDTO启动会报ActivityNotFoundException
2017-09-27 18:15 540当Email未设置账户时,通过ACTION_SENDTO启动会 ... -
java.lang.SecurityException: Permission Denial: reading...requires android.permi
2016-05-12 11:12 2382一直在忙于Gallery,最近遇到了这样的bug,在Setti ... -
android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a read
2015-11-27 14:50 2965android.database.sqlite.SQLiteR ... -
AsyncTask
2015-08-21 17:43 426转自http://blog.csdn.net/hitlion2 ... -
解决IllegalStateException: Can not perform this action after onSaveInstanceState
2015-08-07 18:07 1097转自http://www.cnblogs.com/zgz345 ... -
Android setTag方法的key问题
2015-08-03 19:22 1079转自http://www.cnblogs.com/whitew ... -
ActivityGroup对子Activity的管理
2013-06-27 17:41 2110转自http://eyeandroid.diandian.co ... -
listview在activitygroup切换后无法点击的问题
2013-05-14 10:14 1503转自:http://blog.csdn.net/daguaio ...
相关推荐
前端开发者常常需要在用户进行某些耗时操作(如数据加载、提交表单等)时显示反馈,以告知用户系统正在处理请求。"前端项目-bootstrap-waitingfor"就是这样一个解决方案,它提供了一个等待对话框,并结合了进度条...
MySQL在进行alter table等DDL操作时,有时会出现Waiting for table metadata lock的等待场景。而且,一旦alter table TableA的操作停滞在Waiting for table metadata lock的状态,后续对TableA的任何操作(包括读)...
与npm 您可以使用npm npm install --save bootstrap-waitingfor安装此模块,并如下所示包含它: const waitingDialog = require ( 'bootstrap-waitingfor' ) ;使用在您JavaScript代码中,编写如下内容: ...
waiting for it to exit" 是一个常见的错误信息,意味着当前有另一个应用程序正在占用yum的锁,阻止了你执行新的yum操作。当你试图运行yum命令(如安装、更新或删除软件包)时,可能会遇到这个问题。下面我们将深入...
在使用Android Studio 4.1.2开发环境时,针对Win7 64位操作系统,可能会遇到一些安装和运行上的问题。本文将详细介绍如何解决这些问题,确保Android Studio能顺利运行。 首先,对于“c runtime lib”缺失的问题,这...
在Android应用开发过程中,开发者经常会遇到“Failed to install .apk on device 'emulator-5554': timeout”这样的错误,这通常是由于安装APK到设备(通常是Android模拟器)时超时导致的。这个错误可能会影响开发...
ZeroTier One,1.6.2版本,内网穿透,微软,WINDOWS,MSI安装程序(x86 / x64)
AndroidStudio使用过程中出现的异常 异常信息: Gradle sync failed: Unable to start the daemon process. This problem might be caused by incorrect configuration of the daemon. For example, an ...
标题中的“上传文件时,线程一直waiting”指的是在进行文件上传操作时,程序中的某个线程进入等待状态,这通常涉及到多线程编程和并发控制。这种情况可能由多种原因引起,例如同步机制不当、资源竞争、死锁或阻塞等...
Timeout Waiting for DHCP(解决方案).md
timed out waiting for connection to ZooKeeper解决方案(亲测可用)
waiting-for-the-bus-server提供了一些查询机构、路线、站点和时间的方法。 它还具有空间查询功能,可以查找附近的站点、路线和机构。 有一个为 Pebble Smartwatch 开发的应用程序使用该服务器提供的 API。 你可以...
about to fork child process, waiting until server is ready for connections. forked process: 3560 ERROR: child process failed, exited with error number 1 To see additional information in this output, ...
"Android动态点点省略号闪烁效果的等待控件"是一种常见的设计,它通过连续显示“...”来表示程序正在进行后台操作,同时通过动态闪烁增加用户的交互感,提高用户体验。本篇将详细介绍如何实现这样的控件。 首先,...
We're doing it like everyone does: sending an e-mail to the user, and waiting for the user to click a link. The only validation we do is to check the e-mail with usual regex... but we need to go a ...
广东省博罗县泰美中学七年级英语上册 Module 9 Unit 2 They’re waiting for buses or trains导学案(无答案)(新版)外研版
众所周知,当我们通过ssh远程登录到另一台服务器之后,如果长时间不做操作,那么会被服务器自动登出,并且会告诉你timed out waiting for input: auto-logout。如果不通过tmux这些辅助工具来维持session的话,那么...