Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
门心叼龙
VirtualAPK
提交
a76beb3b
V
VirtualAPK
项目概览
门心叼龙
/
VirtualAPK
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
VirtualAPK
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
a76beb3b
编写于
7月 04, 2018
作者:
S
superq_sky
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Optimized some code extensibility.
上级
254c9aac
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
87 addition
and
64 deletion
+87
-64
CoreLibrary/src/main/java/com/didi/virtualapk/PluginManager.java
...rary/src/main/java/com/didi/virtualapk/PluginManager.java
+31
-12
CoreLibrary/src/main/java/com/didi/virtualapk/delegate/ActivityManagerProxy.java
...va/com/didi/virtualapk/delegate/ActivityManagerProxy.java
+9
-13
CoreLibrary/src/main/java/com/didi/virtualapk/internal/LoadedPlugin.java
.../main/java/com/didi/virtualapk/internal/LoadedPlugin.java
+43
-35
CoreLibrary/src/main/java/com/didi/virtualapk/internal/VAInstrumentation.java
.../java/com/didi/virtualapk/internal/VAInstrumentation.java
+4
-4
未找到文件。
CoreLibrary/src/main/java/com/didi/virtualapk/PluginManager.java
浏览文件 @
a76beb3b
...
...
@@ -48,6 +48,7 @@ import java.io.File;
import
java.io.FileInputStream
;
import
java.io.InputStream
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Proxy
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
...
...
@@ -95,13 +96,13 @@ public class PluginManager {
}
private
void
prepare
()
{
this
.
hookInstrumentationAndHandler
();
this
.
hookSystemServices
();
mComponentsHandler
=
createComponentsHandler
();
hookInstrumentationAndHandler
();
hookSystemServices
();
hookDataBindingUtil
();
}
public
void
init
()
{
mComponentsHandler
=
new
ComponentsHandler
(
this
);
RunUtil
.
getThreadPool
().
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
...
...
@@ -110,10 +111,26 @@ public class PluginManager {
});
}
pr
ivate
void
doInWorkThread
()
{
pr
otected
void
doInWorkThread
()
{
}
private
void
hookDataBindingUtil
()
{
protected
ComponentsHandler
createComponentsHandler
()
{
return
new
ComponentsHandler
(
this
);
}
protected
VAInstrumentation
createInstrumentation
(
Instrumentation
origin
)
throws
Exception
{
return
new
VAInstrumentation
(
this
,
origin
);
}
protected
ActivityManagerProxy
createActivityManagerProxy
(
IActivityManager
origin
)
throws
Exception
{
return
new
ActivityManagerProxy
(
this
,
origin
);
}
protected
LoadedPlugin
createLoadedPlugin
(
File
apk
)
throws
Exception
{
return
new
LoadedPlugin
(
this
,
this
.
mContext
,
apk
);
}
protected
void
hookDataBindingUtil
()
{
Reflector
.
QuietReflector
reflector
=
Reflector
.
QuietReflector
.
on
(
"android.databinding.DataBindingUtil"
).
field
(
"sMapper"
);
Object
old
=
reflector
.
get
();
if
(
old
!=
null
)
{
...
...
@@ -139,7 +156,7 @@ public class PluginManager {
/**
* hookSystemServices, but need to compatible with Android O in future.
*/
pr
ivate
void
hookSystemServices
()
{
pr
otected
void
hookSystemServices
()
{
try
{
Singleton
<
IActivityManager
>
defaultSingleton
;
...
...
@@ -148,7 +165,9 @@ public class PluginManager {
}
else
{
defaultSingleton
=
Reflector
.
on
(
ActivityManagerNative
.
class
).
field
(
"gDefault"
).
get
();
}
IActivityManager
activityManagerProxy
=
ActivityManagerProxy
.
newInstance
(
this
,
defaultSingleton
.
get
());
IActivityManager
origin
=
defaultSingleton
.
get
();
IActivityManager
activityManagerProxy
=
(
IActivityManager
)
Proxy
.
newProxyInstance
(
mContext
.
getClassLoader
(),
new
Class
[]
{
IActivityManager
.
class
},
createActivityManagerProxy
(
origin
));
// Hook IActivityManager from ActivityManagerNative
Reflector
.
with
(
defaultSingleton
).
field
(
"mInstance"
).
set
(
activityManagerProxy
);
...
...
@@ -160,8 +179,8 @@ public class PluginManager {
e
.
printStackTrace
();
}
}
pr
ivate
void
hookInstrumentationAndHandler
()
{
pr
otected
void
hookInstrumentationAndHandler
()
{
try
{
ActivityThread
activityThread
=
ActivityThread
.
currentActivityThread
();
Instrumentation
baseInstrumentation
=
activityThread
.
getInstrumentation
();
...
...
@@ -170,7 +189,7 @@ public class PluginManager {
System
.
exit
(
0
);
}
final
VAInstrumentation
instrumentation
=
new
VAInstrumentation
(
this
,
baseInstrumentation
);
final
VAInstrumentation
instrumentation
=
createInstrumentation
(
baseInstrumentation
);
Reflector
.
with
(
activityThread
).
field
(
"mInstrumentation"
).
set
(
instrumentation
);
Handler
mainHandler
=
Reflector
.
with
(
activityThread
).
method
(
"getHandler"
).
call
();
...
...
@@ -181,7 +200,7 @@ public class PluginManager {
}
}
pr
ivate
void
hookIContentProviderAsNeeded
()
{
pr
otected
void
hookIContentProviderAsNeeded
()
{
Uri
uri
=
Uri
.
parse
(
PluginContentResolver
.
getUri
(
mContext
));
mContext
.
getContentResolver
().
call
(
uri
,
"wakeup"
,
null
,
null
);
try
{
...
...
@@ -237,7 +256,7 @@ public class PluginManager {
in
.
close
();
}
LoadedPlugin
plugin
=
LoadedPlugin
.
create
(
this
,
this
.
mContext
,
apk
);
LoadedPlugin
plugin
=
createLoadedPlugin
(
apk
);
if
(
null
!=
plugin
)
{
this
.
mPlugins
.
put
(
plugin
.
getPackageName
(),
plugin
);
synchronized
(
mCallbacks
)
{
...
...
CoreLibrary/src/main/java/com/didi/virtualapk/delegate/ActivityManagerProxy.java
浏览文件 @
a76beb3b
...
...
@@ -51,10 +51,6 @@ public class ActivityManagerProxy implements InvocationHandler {
public
static
final
int
INTENT_SENDER_ACTIVITY_RESULT
=
3
;
public
static
final
int
INTENT_SENDER_SERVICE
=
4
;
public
static
IActivityManager
newInstance
(
PluginManager
pluginManager
,
IActivityManager
activityManager
)
{
return
(
IActivityManager
)
Proxy
.
newProxyInstance
(
activityManager
.
getClass
().
getClassLoader
(),
new
Class
[]
{
IActivityManager
.
class
},
new
ActivityManagerProxy
(
pluginManager
,
activityManager
));
}
private
PluginManager
mPluginManager
;
private
IActivityManager
mActivityManager
;
...
...
@@ -135,7 +131,7 @@ public class ActivityManagerProxy implements InvocationHandler {
}
pr
ivate
Object
startService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
pr
otected
Object
startService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
IApplicationThread
appThread
=
(
IApplicationThread
)
args
[
0
];
Intent
target
=
(
Intent
)
args
[
1
];
ResolveInfo
resolveInfo
=
this
.
mPluginManager
.
resolveService
(
target
,
0
);
...
...
@@ -147,7 +143,7 @@ public class ActivityManagerProxy implements InvocationHandler {
return
startDelegateServiceForTarget
(
target
,
resolveInfo
.
serviceInfo
,
null
,
RemoteService
.
EXTRA_COMMAND_START_SERVICE
);
}
pr
ivate
Object
stopService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
pr
otected
Object
stopService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
Intent
target
=
(
Intent
)
args
[
1
];
ResolveInfo
resolveInfo
=
this
.
mPluginManager
.
resolveService
(
target
,
0
);
if
(
null
==
resolveInfo
||
null
==
resolveInfo
.
serviceInfo
)
{
...
...
@@ -159,7 +155,7 @@ public class ActivityManagerProxy implements InvocationHandler {
return
1
;
}
pr
ivate
Object
stopServiceToken
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
pr
otected
Object
stopServiceToken
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
ComponentName
component
=
(
ComponentName
)
args
[
0
];
Intent
target
=
new
Intent
().
setComponent
(
component
);
ResolveInfo
resolveInfo
=
this
.
mPluginManager
.
resolveService
(
target
,
0
);
...
...
@@ -172,7 +168,7 @@ public class ActivityManagerProxy implements InvocationHandler {
return
true
;
}
pr
ivate
Object
bindService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
pr
otected
Object
bindService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
Intent
target
=
(
Intent
)
args
[
2
];
ResolveInfo
resolveInfo
=
this
.
mPluginManager
.
resolveService
(
target
,
0
);
if
(
null
==
resolveInfo
||
null
==
resolveInfo
.
serviceInfo
)
{
...
...
@@ -187,7 +183,7 @@ public class ActivityManagerProxy implements InvocationHandler {
return
1
;
}
pr
ivate
Object
unbindService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
pr
otected
Object
unbindService
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
IBinder
iServiceConnection
=
(
IBinder
)
args
[
0
];
Intent
target
=
mPluginManager
.
getComponentsHandler
().
forgetIServiceConnection
(
iServiceConnection
);
if
(
target
==
null
)
{
...
...
@@ -200,12 +196,12 @@ public class ActivityManagerProxy implements InvocationHandler {
return
true
;
}
pr
ivate
ComponentName
startDelegateServiceForTarget
(
Intent
target
,
ServiceInfo
serviceInfo
,
Bundle
extras
,
int
command
)
{
pr
otected
ComponentName
startDelegateServiceForTarget
(
Intent
target
,
ServiceInfo
serviceInfo
,
Bundle
extras
,
int
command
)
{
Intent
wrapperIntent
=
wrapperTargetIntent
(
target
,
serviceInfo
,
extras
,
command
);
return
mPluginManager
.
getHostContext
().
startService
(
wrapperIntent
);
}
pr
ivate
Intent
wrapperTargetIntent
(
Intent
target
,
ServiceInfo
serviceInfo
,
Bundle
extras
,
int
command
)
{
pr
otected
Intent
wrapperTargetIntent
(
Intent
target
,
ServiceInfo
serviceInfo
,
Bundle
extras
,
int
command
)
{
// fill in service with ComponentName
target
.
setComponent
(
new
ComponentName
(
serviceInfo
.
packageName
,
serviceInfo
.
name
));
String
pluginLocation
=
mPluginManager
.
getLoadedPlugin
(
target
.
getComponent
()).
getLocation
();
...
...
@@ -225,7 +221,7 @@ public class ActivityManagerProxy implements InvocationHandler {
return
intent
;
}
pr
ivate
void
getIntentSender
(
Method
method
,
Object
[]
args
)
{
pr
otected
void
getIntentSender
(
Method
method
,
Object
[]
args
)
{
String
hostPackageName
=
mPluginManager
.
getHostContext
().
getPackageName
();
args
[
1
]
=
hostPackageName
;
...
...
@@ -246,7 +242,7 @@ public class ActivityManagerProxy implements InvocationHandler {
}
}
pr
ivate
void
overridePendingTransition
(
Method
method
,
Object
[]
args
)
{
pr
otected
void
overridePendingTransition
(
Method
method
,
Object
[]
args
)
{
String
hostPackageName
=
mPluginManager
.
getHostContext
().
getPackageName
();
args
[
1
]
=
hostPackageName
;
}
...
...
CoreLibrary/src/main/java/com/didi/virtualapk/internal/LoadedPlugin.java
浏览文件 @
a76beb3b
...
...
@@ -78,11 +78,7 @@ public final class LoadedPlugin {
public
static
final
String
TAG
=
"LoadedPlugin"
;
public
static
LoadedPlugin
create
(
PluginManager
pluginManager
,
Context
host
,
File
apk
)
throws
Exception
{
return
new
LoadedPlugin
(
pluginManager
,
host
,
apk
);
}
private
static
ClassLoader
createClassLoader
(
Context
context
,
File
apk
,
File
libsDir
,
ClassLoader
parent
)
{
protected
ClassLoader
createClassLoader
(
Context
context
,
File
apk
,
File
libsDir
,
ClassLoader
parent
)
{
File
dexOutputDir
=
context
.
getDir
(
Constants
.
OPTIMIZE_DIR
,
Context
.
MODE_PRIVATE
);
String
dexOutputPath
=
dexOutputDir
.
getAbsolutePath
();
DexClassLoader
loader
=
new
DexClassLoader
(
apk
.
getAbsolutePath
(),
dexOutputPath
,
libsDir
.
getAbsolutePath
(),
parent
);
...
...
@@ -98,7 +94,7 @@ public final class LoadedPlugin {
return
loader
;
}
pr
ivate
static
AssetManager
createAssetManager
(
Context
context
,
File
apk
)
{
pr
otected
AssetManager
createAssetManager
(
Context
context
,
File
apk
)
{
try
{
AssetManager
am
=
AssetManager
.
class
.
newInstance
();
Reflector
.
with
(
am
).
method
(
"addAssetPath"
,
String
.
class
).
call
(
apk
.
getAbsolutePath
());
...
...
@@ -109,7 +105,7 @@ public final class LoadedPlugin {
}
}
pr
ivate
static
Resources
createResources
(
Context
context
,
String
packageName
,
File
apk
)
throws
Exception
{
pr
otected
Resources
createResources
(
Context
context
,
String
packageName
,
File
apk
)
throws
Exception
{
if
(
Constants
.
COMBINE_RESOURCES
)
{
return
ResourcesManager
.
createResources
(
context
,
packageName
,
apk
);
}
else
{
...
...
@@ -118,33 +114,45 @@ public final class LoadedPlugin {
return
new
Resources
(
assetManager
,
hostResources
.
getDisplayMetrics
(),
hostResources
.
getConfiguration
());
}
}
protected
PluginPackageManager
createPluginPackageManager
()
{
return
new
PluginPackageManager
();
}
public
PluginContext
createPluginContext
(
Context
context
)
{
if
(
context
==
null
)
{
return
new
PluginContext
(
this
);
}
return
new
PluginContext
(
this
,
context
);
}
pr
ivate
static
ResolveInfo
chooseBestActivity
(
Intent
intent
,
String
s
,
int
flags
,
List
<
ResolveInfo
>
query
)
{
pr
otected
ResolveInfo
chooseBestActivity
(
Intent
intent
,
String
s
,
int
flags
,
List
<
ResolveInfo
>
query
)
{
return
query
.
get
(
0
);
}
pr
ivate
final
String
mLocation
;
pr
ivate
PluginManager
mPluginManager
;
pr
ivate
Context
mHostContext
;
pr
ivate
Context
mPluginContext
;
pr
ivate
final
File
mNativeLibDir
;
pr
ivate
final
PackageParser
.
Package
mPackage
;
pr
ivate
final
PackageInfo
mPackageInfo
;
pr
ivate
Resources
mResources
;
pr
ivate
ClassLoader
mClassLoader
;
pr
ivate
PluginPackageManager
mPackageManager
;
pr
ivate
Map
<
ComponentName
,
ActivityInfo
>
mActivityInfos
;
pr
ivate
Map
<
ComponentName
,
ServiceInfo
>
mServiceInfos
;
pr
ivate
Map
<
ComponentName
,
ActivityInfo
>
mReceiverInfos
;
pr
ivate
Map
<
ComponentName
,
ProviderInfo
>
mProviderInfos
;
pr
ivate
Map
<
String
,
ProviderInfo
>
mProviders
;
// key is authorities of provider
pr
ivate
Map
<
ComponentName
,
InstrumentationInfo
>
mInstrumentationInfos
;
pr
ivate
Application
mApplication
;
pr
otected
final
String
mLocation
;
pr
otected
PluginManager
mPluginManager
;
pr
otected
Context
mHostContext
;
pr
otected
Context
mPluginContext
;
pr
otected
final
File
mNativeLibDir
;
pr
otected
final
PackageParser
.
Package
mPackage
;
pr
otected
final
PackageInfo
mPackageInfo
;
pr
otected
Resources
mResources
;
pr
otected
ClassLoader
mClassLoader
;
pr
otected
PluginPackageManager
mPackageManager
;
pr
otected
Map
<
ComponentName
,
ActivityInfo
>
mActivityInfos
;
pr
otected
Map
<
ComponentName
,
ServiceInfo
>
mServiceInfos
;
pr
otected
Map
<
ComponentName
,
ActivityInfo
>
mReceiverInfos
;
pr
otected
Map
<
ComponentName
,
ProviderInfo
>
mProviderInfos
;
pr
otected
Map
<
String
,
ProviderInfo
>
mProviders
;
// key is authorities of provider
pr
otected
Map
<
ComponentName
,
InstrumentationInfo
>
mInstrumentationInfos
;
pr
otected
Application
mApplication
;
@UiThread
LoadedPlugin
(
PluginManager
pluginManager
,
Context
context
,
File
apk
)
throws
Exception
{
public
LoadedPlugin
(
PluginManager
pluginManager
,
Context
context
,
File
apk
)
throws
Exception
{
if
(
Thread
.
currentThread
()
!=
Looper
.
getMainLooper
().
getThread
())
{
throw
new
RuntimeException
(
"plugin mast be created by UI thread."
);
}
...
...
@@ -176,8 +184,8 @@ public final class LoadedPlugin {
this
.
mPackageInfo
.
versionCode
=
this
.
mPackage
.
mVersionCode
;
this
.
mPackageInfo
.
versionName
=
this
.
mPackage
.
mVersionName
;
this
.
mPackageInfo
.
permissions
=
new
PermissionInfo
[
0
];
this
.
mPackageManager
=
new
PluginPackageManager
();
this
.
mPluginContext
=
new
PluginContext
(
this
);
this
.
mPackageManager
=
create
PluginPackageManager
();
this
.
mPluginContext
=
createPluginContext
(
null
);
this
.
mNativeLibDir
=
context
.
getDir
(
Constants
.
NATIVE_DIR
,
Context
.
MODE_PRIVATE
);
this
.
mResources
=
createResources
(
context
,
getPackageName
(),
apk
);
this
.
mClassLoader
=
createClassLoader
(
context
,
apk
,
this
.
mNativeLibDir
,
context
.
getClassLoader
());
...
...
@@ -233,7 +241,7 @@ public final class LoadedPlugin {
this
.
mPackageInfo
.
receivers
=
receivers
.
values
().
toArray
(
new
ActivityInfo
[
receivers
.
size
()]);
}
pr
ivate
void
tryToCopyNativeLib
(
File
apk
)
throws
Exception
{
pr
otected
void
tryToCopyNativeLib
(
File
apk
)
throws
Exception
{
PluginUtil
.
copyNativeLib
(
apk
,
mHostContext
,
mPackageInfo
,
mNativeLibDir
);
}
...
...
@@ -371,7 +379,7 @@ public final class LoadedPlugin {
Reflector
.
QuietReflector
.
with
(
this
.
mResources
).
field
(
"mThemeResId"
).
set
(
resid
);
}
pr
ivate
Application
makeApplication
(
boolean
forceDefaultAppClass
,
Instrumentation
instrumentation
)
{
pr
otected
Application
makeApplication
(
boolean
forceDefaultAppClass
,
Instrumentation
instrumentation
)
{
if
(
null
!=
this
.
mApplication
)
{
return
this
.
mApplication
;
}
...
...
@@ -493,7 +501,7 @@ public final class LoadedPlugin {
return
this
.
mProviders
.
get
(
name
);
}
pr
ivate
boolean
match
(
PackageParser
.
Component
component
,
ComponentName
target
)
{
pr
otected
boolean
match
(
PackageParser
.
Component
component
,
ComponentName
target
)
{
ComponentName
source
=
component
.
getComponentName
();
if
(
source
==
target
)
return
true
;
if
(
source
!=
null
&&
target
!=
null
...
...
@@ -508,9 +516,9 @@ public final class LoadedPlugin {
/**
* @author johnsonlee
*/
pr
ivate
class
PluginPackageManager
extends
PackageManager
{
pr
otected
class
PluginPackageManager
extends
PackageManager
{
pr
ivate
PackageManager
mHostPackageManager
=
mHostContext
.
getPackageManager
();
pr
otected
PackageManager
mHostPackageManager
=
mHostContext
.
getPackageManager
();
@Override
public
PackageInfo
getPackageInfo
(
String
packageName
,
int
flags
)
throws
NameNotFoundException
{
...
...
CoreLibrary/src/main/java/com/didi/virtualapk/internal/VAInstrumentation.java
浏览文件 @
a76beb3b
...
...
@@ -86,7 +86,7 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
return
mBase
.
execStartActivity
(
who
,
contextThread
,
token
,
target
,
intent
,
requestCode
,
options
);
}
pr
ivate
void
injectIntent
(
Intent
intent
)
{
pr
otected
void
injectIntent
(
Intent
intent
)
{
mPluginManager
.
getComponentsHandler
().
transformIntentToExplicitAsNeeded
(
intent
);
// null component is an implicitly intent
if
(
intent
.
getComponent
()
!=
null
)
{
...
...
@@ -161,7 +161,7 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
mBase
.
callActivityOnCreate
(
activity
,
icicle
,
persistentState
);
}
pr
ivate
void
injectActivity
(
Activity
activity
)
{
pr
otected
void
injectActivity
(
Activity
activity
)
{
final
Intent
intent
=
activity
.
getIntent
();
if
(
PluginUtil
.
isIntentFromPlugin
(
intent
))
{
Context
base
=
activity
.
getBaseContext
();
...
...
@@ -169,7 +169,7 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
LoadedPlugin
plugin
=
this
.
mPluginManager
.
getLoadedPlugin
(
intent
);
Reflector
.
with
(
base
).
field
(
"mResources"
).
set
(
plugin
.
getResources
());
Reflector
reflector
=
Reflector
.
with
(
activity
);
reflector
.
field
(
"mBase"
).
set
(
new
PluginContext
(
plugin
,
activity
.
getBaseContext
()));
reflector
.
field
(
"mBase"
).
set
(
plugin
.
createPluginContext
(
activity
.
getBaseContext
()));
reflector
.
field
(
"mApplication"
).
set
(
plugin
.
getApplication
());
// set screenOrientation
...
...
@@ -224,7 +224,7 @@ public class VAInstrumentation extends Instrumentation implements Handler.Callba
return
mBase
.
getComponentName
();
}
pr
ivate
Activity
newActivity
(
Activity
activity
)
{
pr
otected
Activity
newActivity
(
Activity
activity
)
{
synchronized
(
mActivities
)
{
for
(
int
i
=
mActivities
.
size
()
-
1
;
i
>=
0
;
i
--)
{
if
(
mActivities
.
get
(
i
).
get
()
==
null
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录