Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
qq_34031325
engine
提交
256db4bc
E
engine
项目概览
qq_34031325
/
engine
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
engine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
256db4bc
编写于
2月 15, 2019
作者:
M
Matt Carroll
提交者:
GitHub
2月 15, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Android embedding refactor pr3 add remaining systemchannels (#7738)
上级
02d7ca31
变更
11
展开全部
显示空白变更内容
内联
并排
Showing
11 changed file
with
1570 addition
and
562 deletion
+1570
-562
ci/licenses_golden/licenses_flutter
ci/licenses_golden/licenses_flutter
+2
-0
shell/platform/android/BUILD.gn
shell/platform/android/BUILD.gn
+2
-0
shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java
...embedding/engine/systemchannels/AccessibilityChannel.java
+120
-0
shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java
.../embedding/engine/systemchannels/LocalizationChannel.java
+16
-7
shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java
...tter/embedding/engine/systemchannels/PlatformChannel.java
+592
-5
shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java
...ter/embedding/engine/systemchannels/TextInputChannel.java
+406
-0
shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java
...oid/io/flutter/plugin/editing/InputConnectionAdaptor.java
+26
-32
shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
...rm/android/io/flutter/plugin/editing/TextInputPlugin.java
+83
-98
shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java
...rm/android/io/flutter/plugin/platform/PlatformPlugin.java
+157
-218
shell/platform/android/io/flutter/view/AccessibilityBridge.java
...platform/android/io/flutter/view/AccessibilityBridge.java
+139
-155
shell/platform/android/io/flutter/view/FlutterView.java
shell/platform/android/io/flutter/view/FlutterView.java
+27
-47
未找到文件。
ci/licenses_golden/licenses_flutter
浏览文件 @
256db4bc
...
...
@@ -446,6 +446,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/D
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformMessageHandler.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/KeyEventChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/LifecycleChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java
...
...
@@ -453,6 +454,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/system
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SettingsChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SystemChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/ActivityLifecycleListener.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/BasicMessageChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/common/BinaryCodec.java
...
...
shell/platform/android/BUILD.gn
浏览文件 @
256db4bc
...
...
@@ -114,6 +114,7 @@ java_library("flutter_shell_java") {
"io/flutter/embedding/engine/dart/PlatformMessageHandler.java",
"io/flutter/embedding/engine/renderer/FlutterRenderer.java",
"io/flutter/embedding/engine/renderer/OnFirstFrameRenderedListener.java",
"io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java",
"io/flutter/embedding/engine/systemchannels/KeyEventChannel.java",
"io/flutter/embedding/engine/systemchannels/LifecycleChannel.java",
"io/flutter/embedding/engine/systemchannels/LocalizationChannel.java",
...
...
@@ -121,6 +122,7 @@ java_library("flutter_shell_java") {
"io/flutter/embedding/engine/systemchannels/PlatformChannel.java",
"io/flutter/embedding/engine/systemchannels/SettingsChannel.java",
"io/flutter/embedding/engine/systemchannels/SystemChannel.java",
"io/flutter/embedding/engine/systemchannels/TextInputChannel.java",
"io/flutter/plugin/common/ActivityLifecycleListener.java",
"io/flutter/plugin/common/BasicMessageChannel.java",
"io/flutter/plugin/common/BinaryCodec.java",
...
...
shell/platform/android/io/flutter/embedding/engine/systemchannels/AccessibilityChannel.java
0 → 100644
浏览文件 @
256db4bc
package
io.flutter.embedding.engine.systemchannels
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
java.util.HashMap
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.plugin.common.BasicMessageChannel
;
import
io.flutter.plugin.common.StandardMessageCodec
;
/**
* System channel that sends accessibility requests and events from Flutter to Android.
* <p>
* See {@link AccessibilityMessageHandler}, which lists all accessibility requests and
* events that might be sent from Flutter to the Android platform.
*/
public
class
AccessibilityChannel
{
@NonNull
public
BasicMessageChannel
<
Object
>
channel
;
@Nullable
private
AccessibilityMessageHandler
handler
;
private
final
BasicMessageChannel
.
MessageHandler
<
Object
>
parsingMessageHandler
=
new
BasicMessageChannel
.
MessageHandler
<
Object
>()
{
@Override
public
void
onMessage
(
Object
message
,
BasicMessageChannel
.
Reply
<
Object
>
reply
)
{
// If there is no handler to respond to this message then we don't need to
// parse it. Return.
if
(
handler
==
null
)
{
return
;
}
@SuppressWarnings
(
"unchecked"
)
final
HashMap
<
String
,
Object
>
annotatedEvent
=
(
HashMap
<
String
,
Object
>)
message
;
final
String
type
=
(
String
)
annotatedEvent
.
get
(
"type"
);
@SuppressWarnings
(
"unchecked"
)
final
HashMap
<
String
,
Object
>
data
=
(
HashMap
<
String
,
Object
>)
annotatedEvent
.
get
(
"data"
);
switch
(
type
)
{
case
"announce"
:
String
announceMessage
=
(
String
)
data
.
get
(
"message"
);
if
(
announceMessage
!=
null
)
{
handler
.
announce
(
announceMessage
);
}
break
;
case
"tap"
:
{
Integer
nodeId
=
(
Integer
)
annotatedEvent
.
get
(
"nodeId"
);
if
(
nodeId
!=
null
)
{
handler
.
onTap
(
nodeId
);
}
break
;
}
case
"longPress"
:
{
Integer
nodeId
=
(
Integer
)
annotatedEvent
.
get
(
"nodeId"
);
if
(
nodeId
!=
null
)
{
handler
.
onLongPress
(
nodeId
);
}
break
;
}
case
"tooltip"
:
{
String
tooltipMessage
=
(
String
)
data
.
get
(
"message"
);
if
(
tooltipMessage
!=
null
)
{
handler
.
onTooltip
(
tooltipMessage
);
}
break
;
}
}
}
};
/**
* Constructs an {@code AccessibilityChannel} that connects Android to the Dart code
* running in {@code dartExecutor}.
*
* The given {@code dartExecutor} is permitted to be idle or executing code.
*
* See {@link DartExecutor}.
*/
public
AccessibilityChannel
(
@NonNull
DartExecutor
dartExecutor
)
{
channel
=
new
BasicMessageChannel
<>(
dartExecutor
,
"flutter/accessibility"
,
StandardMessageCodec
.
INSTANCE
);
channel
.
setMessageHandler
(
parsingMessageHandler
);
}
/**
* Sets the {@link AccessibilityMessageHandler} which receives all events and requests
* that are parsed from the underlying accessibility channel.
*/
public
void
setAccessibilityMessageHandler
(
@Nullable
AccessibilityMessageHandler
handler
)
{
this
.
handler
=
handler
;
}
/**
* Handler that receives accessibility messages sent from Flutter to Android
* through a given {@link AccessibilityChannel}.
*
* To register an {@code AccessibilityMessageHandler} with a {@link AccessibilityChannel},
* see {@link AccessibilityChannel#setAccessibilityMessageHandler(AccessibilityMessageHandler)}.
*/
public
interface
AccessibilityMessageHandler
{
/**
* The Dart application would like the given {@code message} to be announced.
*/
void
announce
(
@NonNull
String
message
);
/**
* The user has tapped on the artifact with the given {@code nodeId}.
*/
void
onTap
(
int
nodeId
);
/**
* The user has long pressed on the artifact with the given {@code nodeId}.
*/
void
onLongPress
(
int
nodeId
);
/**
* The user has opened a popup window, menu, dialog, etc.
*/
void
onTooltip
(
@NonNull
String
message
);
}
}
shell/platform/android/io/flutter/embedding/engine/systemchannels/LocalizationChannel.java
浏览文件 @
256db4bc
...
...
@@ -6,14 +6,17 @@ package io.flutter.embedding.engine.systemchannels;
import
android.support.annotation.NonNull
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.Locale
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.plugin.common.JSONMethodCodec
;
import
io.flutter.plugin.common.MethodChannel
;
/**
*
TODO(mattcarroll): fill in javadoc for LocalizationChannel
.
*
Sends the platform's locales to Dart
.
*/
public
class
LocalizationChannel
{
...
...
@@ -24,12 +27,18 @@ public class LocalizationChannel {
this
.
channel
=
new
MethodChannel
(
dartExecutor
,
"flutter/localization"
,
JSONMethodCodec
.
INSTANCE
);
}
public
void
setLocale
(
String
language
,
String
country
)
{
channel
.
invokeMethod
(
"setLocale"
,
Arrays
.
asList
(
language
,
country
));
/**
* Send the given {@code locales} to Dart.
*/
public
void
sendLocales
(
List
<
Locale
>
locales
)
{
List
<
String
>
data
=
new
ArrayList
<>();
for
(
Locale
locale
:
locales
)
{
data
.
add
(
locale
.
getLanguage
());
data
.
add
(
locale
.
getCountry
());
data
.
add
(
locale
.
getScript
());
data
.
add
(
locale
.
getVariant
());
}
public
void
setMethodCallHandler
(
MethodChannel
.
MethodCallHandler
handler
)
{
channel
.
setMethodCallHandler
(
handler
);
channel
.
invokeMethod
(
"setLocale"
,
data
);
}
}
shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java
浏览文件 @
256db4bc
此差异已折叠。
点击以展开。
shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java
0 → 100644
浏览文件 @
256db4bc
package
io.flutter.embedding.engine.systemchannels
;
import
android.support.annotation.NonNull
;
import
android.support.annotation.Nullable
;
import
android.view.inputmethod.EditorInfo
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.plugin.common.JSONMethodCodec
;
import
io.flutter.plugin.common.MethodCall
;
import
io.flutter.plugin.common.MethodChannel
;
/**
* {@link TextInputChannel} is a platform channel between Android and Flutter that is used to
* communicate information about the user's text input.
* <p>
* When the user presses an action button like "done" or "next", that action is sent from Android
* to Flutter through this {@link TextInputChannel}.
* <p>
* When an input system in the Flutter app wants to show the keyboard, or hide it, or configure
* editing state, etc. a message is sent from Flutter to Android through this {@link TextInputChannel}.
* <p>
* {@link TextInputChannel} comes with a default {@link io.flutter.plugin.common.MethodChannel.MethodCallHandler}
* that parses incoming messages from Flutter. Register a {@link TextInputMethodHandler} to respond
* to standard Flutter text input messages.
*/
public
class
TextInputChannel
{
@NonNull
public
final
MethodChannel
channel
;
@Nullable
private
TextInputMethodHandler
textInputMethodHandler
;
private
final
MethodChannel
.
MethodCallHandler
parsingMethodHandler
=
new
MethodChannel
.
MethodCallHandler
()
{
@Override
public
void
onMethodCall
(
MethodCall
call
,
MethodChannel
.
Result
result
)
{
if
(
textInputMethodHandler
==
null
)
{
// If no explicit TextInputMethodHandler has been registered then we don't
// need to forward this call to an API. Return.
return
;
}
String
method
=
call
.
method
;
Object
args
=
call
.
arguments
;
switch
(
method
)
{
case
"TextInput.show"
:
textInputMethodHandler
.
show
();
result
.
success
(
null
);
break
;
case
"TextInput.hide"
:
textInputMethodHandler
.
hide
();
result
.
success
(
null
);
break
;
case
"TextInput.setClient"
:
try
{
final
JSONArray
argumentList
=
(
JSONArray
)
args
;
final
int
textInputClientId
=
argumentList
.
getInt
(
0
);
final
JSONObject
jsonConfiguration
=
argumentList
.
getJSONObject
(
1
);
textInputMethodHandler
.
setClient
(
textInputClientId
,
Configuration
.
fromJson
(
jsonConfiguration
));
result
.
success
(
null
);
}
catch
(
JSONException
|
NoSuchFieldException
exception
)
{
// JSONException: missing keys or bad value types.
// NoSuchFieldException: one or more values were invalid.
result
.
error
(
"error"
,
exception
.
getMessage
(),
null
);
}
break
;
case
"TextInput.setEditingState"
:
try
{
final
JSONObject
editingState
=
(
JSONObject
)
args
;
textInputMethodHandler
.
setEditingState
(
TextEditState
.
fromJson
(
editingState
));
result
.
success
(
null
);
}
catch
(
JSONException
exception
)
{
result
.
error
(
"error"
,
exception
.
getMessage
(),
null
);
}
break
;
case
"TextInput.clearClient"
:
textInputMethodHandler
.
clearClient
();
result
.
success
(
null
);
break
;
default
:
result
.
notImplemented
();
break
;
}
}
};
/**
* Constructs a {@code TextInputChannel} that connects Android to the Dart code
* running in {@code dartExecutor}.
*
* The given {@code dartExecutor} is permitted to be idle or executing code.
*
* See {@link DartExecutor}.
*/
public
TextInputChannel
(
@NonNull
DartExecutor
dartExecutor
)
{
this
.
channel
=
new
MethodChannel
(
dartExecutor
,
"flutter/textinput"
,
JSONMethodCodec
.
INSTANCE
);
channel
.
setMethodCallHandler
(
parsingMethodHandler
);
}
/**
* Instructs Flutter to update its text input editing state to reflect the given configuration.
*/
public
void
updateEditingState
(
int
inputClientId
,
String
text
,
int
selectionStart
,
int
selectionEnd
,
int
composingStart
,
int
composingEnd
)
{
HashMap
<
Object
,
Object
>
state
=
new
HashMap
<>();
state
.
put
(
"text"
,
text
);
state
.
put
(
"selectionBase"
,
selectionStart
);
state
.
put
(
"selectionExtent"
,
selectionEnd
);
state
.
put
(
"composingBase"
,
composingStart
);
state
.
put
(
"composingExtent"
,
composingEnd
);
channel
.
invokeMethod
(
"TextInputClient.updateEditingState"
,
Arrays
.
asList
(
inputClientId
,
state
)
);
}
/**
* Instructs Flutter to execute a "newline" action.
*/
public
void
newline
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.newline"
)
);
}
/**
* Instructs Flutter to execute a "go" action.
*/
public
void
go
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.go"
)
);
}
/**
* Instructs Flutter to execute a "search" action.
*/
public
void
search
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.search"
)
);
}
/**
* Instructs Flutter to execute a "send" action.
*/
public
void
send
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.send"
)
);
}
/**
* Instructs Flutter to execute a "done" action.
*/
public
void
done
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.done"
)
);
}
/**
* Instructs Flutter to execute a "next" action.
*/
public
void
next
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.next"
)
);
}
/**
* Instructs Flutter to execute a "previous" action.
*/
public
void
previous
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.previous"
)
);
}
/**
* Instructs Flutter to execute an "unspecified" action.
*/
public
void
unspecifiedAction
(
int
inputClientId
)
{
channel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
inputClientId
,
"TextInputAction.unspecified"
)
);
}
/**
* Sets the {@link TextInputMethodHandler} which receives all events and requests
* that are parsed from the underlying platform channel.
*/
public
void
setTextInputMethodHandler
(
@Nullable
TextInputMethodHandler
textInputMethodHandler
)
{
this
.
textInputMethodHandler
=
textInputMethodHandler
;
}
public
interface
TextInputMethodHandler
{
// TODO(mattcarroll): javadoc
void
show
();
// TODO(mattcarroll): javadoc
void
hide
();
// TODO(mattcarroll): javadoc
void
setClient
(
int
textInputClientId
,
@NonNull
Configuration
configuration
);
// TODO(mattcarroll): javadoc
void
setEditingState
(
@NonNull
TextEditState
editingState
);
// TODO(mattcarroll): javadoc
void
clearClient
();
}
/**
* A text editing configuration.
*/
public
static
class
Configuration
{
public
static
Configuration
fromJson
(
@NonNull
JSONObject
json
)
throws
JSONException
,
NoSuchFieldException
{
final
String
inputActionName
=
json
.
getString
(
"inputAction"
);
if
(
inputActionName
==
null
)
{
throw
new
JSONException
(
"Configuration JSON missing 'inputAction' property."
);
}
final
Integer
inputAction
=
inputActionFromTextInputAction
(
inputActionName
);
return
new
Configuration
(
json
.
optBoolean
(
"obscureText"
),
json
.
optBoolean
(
"autocorrect"
,
true
),
TextCapitalization
.
fromValue
(
json
.
getString
(
"textCapitalization"
)),
InputType
.
fromJson
(
json
.
getJSONObject
(
"inputType"
)),
inputAction
,
json
.
optString
(
"actionLabel"
)
);
}
private
static
Integer
inputActionFromTextInputAction
(
@NonNull
String
inputAction
)
{
switch
(
inputAction
)
{
case
"TextInputAction.newline"
:
return
EditorInfo
.
IME_ACTION_NONE
;
case
"TextInputAction.none"
:
return
EditorInfo
.
IME_ACTION_NONE
;
case
"TextInputAction.unspecified"
:
return
EditorInfo
.
IME_ACTION_UNSPECIFIED
;
case
"TextInputAction.done"
:
return
EditorInfo
.
IME_ACTION_DONE
;
case
"TextInputAction.go"
:
return
EditorInfo
.
IME_ACTION_GO
;
case
"TextInputAction.search"
:
return
EditorInfo
.
IME_ACTION_SEARCH
;
case
"TextInputAction.send"
:
return
EditorInfo
.
IME_ACTION_SEND
;
case
"TextInputAction.next"
:
return
EditorInfo
.
IME_ACTION_NEXT
;
case
"TextInputAction.previous"
:
return
EditorInfo
.
IME_ACTION_PREVIOUS
;
default
:
// Present default key if bad input type is given.
return
EditorInfo
.
IME_ACTION_UNSPECIFIED
;
}
}
public
final
boolean
obscureText
;
public
final
boolean
autocorrect
;
@NonNull
public
final
TextCapitalization
textCapitalization
;
@NonNull
public
final
InputType
inputType
;
@Nullable
public
final
Integer
inputAction
;
@Nullable
public
final
String
actionLabel
;
public
Configuration
(
boolean
obscureText
,
boolean
autocorrect
,
@NonNull
TextCapitalization
textCapitalization
,
@NonNull
InputType
inputType
,
@Nullable
Integer
inputAction
,
@Nullable
String
actionLabel
)
{
this
.
obscureText
=
obscureText
;
this
.
autocorrect
=
autocorrect
;
this
.
textCapitalization
=
textCapitalization
;
this
.
inputType
=
inputType
;
this
.
inputAction
=
inputAction
;
this
.
actionLabel
=
actionLabel
;
}
}
/**
* A text input type.
*
* If the {@link #type} is {@link TextInputType#NUMBER}, this {@code InputType} also
* reports whether that number {@link #isSigned} and {@link #isDecimal}.
*/
public
static
class
InputType
{
@NonNull
public
static
InputType
fromJson
(
@NonNull
JSONObject
json
)
throws
JSONException
,
NoSuchFieldException
{
return
new
InputType
(
TextInputType
.
fromValue
(
json
.
getString
(
"name"
)),
json
.
optBoolean
(
"signed"
,
false
),
json
.
optBoolean
(
"decimal"
,
false
)
);
}
@NonNull
public
final
TextInputType
type
;
public
final
boolean
isSigned
;
public
final
boolean
isDecimal
;
public
InputType
(
@NonNull
TextInputType
type
,
boolean
isSigned
,
boolean
isDecimal
)
{
this
.
type
=
type
;
this
.
isSigned
=
isSigned
;
this
.
isDecimal
=
isDecimal
;
}
}
/**
* Types of text input.
*/
public
enum
TextInputType
{
DATETIME
(
"TextInputType.datetime"
),
NUMBER
(
"TextInputType.number"
),
PHONE
(
"TextInputType.phone"
),
MULTILINE
(
"TextInputType.multiline"
),
EMAIL_ADDRESS
(
"TextInputType.emailAddress"
),
URL
(
"TextInputType.url"
);
static
TextInputType
fromValue
(
@NonNull
String
encodedName
)
throws
NoSuchFieldException
{
for
(
TextInputType
textInputType
:
TextInputType
.
values
())
{
if
(
textInputType
.
encodedName
.
equals
(
encodedName
))
{
return
textInputType
;
}
}
throw
new
NoSuchFieldException
(
"No such TextInputType: "
+
encodedName
);
}
@NonNull
private
final
String
encodedName
;
TextInputType
(
@NonNull
String
encodedName
)
{
this
.
encodedName
=
encodedName
;
}
}
/**
* Text capitalization schemes.
*/
public
enum
TextCapitalization
{
CHARACTERS
(
"TextCapitalization.characters"
),
WORDS
(
"TextCapitalization.words"
),
SENTENCES
(
"TextCapitalization.sentences"
);
static
TextCapitalization
fromValue
(
@NonNull
String
encodedName
)
throws
NoSuchFieldException
{
for
(
TextCapitalization
textCapitalization
:
TextCapitalization
.
values
())
{
if
(
textCapitalization
.
encodedName
.
equals
(
encodedName
))
{
return
textCapitalization
;
}
}
throw
new
NoSuchFieldException
(
"No such TextCapitalization: "
+
encodedName
);
}
@NonNull
private
final
String
encodedName
;
TextCapitalization
(
@NonNull
String
encodedName
)
{
this
.
encodedName
=
encodedName
;
}
}
/**
* State of an on-going text editing session.
*/
public
static
class
TextEditState
{
public
static
TextEditState
fromJson
(
@NonNull
JSONObject
textEditState
)
throws
JSONException
{
return
new
TextEditState
(
textEditState
.
getString
(
"text"
),
textEditState
.
getInt
(
"selectionBase"
),
textEditState
.
getInt
(
"selectionExtent"
)
);
}
@NonNull
public
final
String
text
;
public
final
int
selectionStart
;
public
final
int
selectionEnd
;
public
TextEditState
(
@NonNull
String
text
,
int
selectionStart
,
int
selectionEnd
)
{
this
.
text
=
text
;
this
.
selectionStart
=
selectionStart
;
this
.
selectionEnd
=
selectionEnd
;
}
}
}
shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java
浏览文件 @
256db4bc
...
...
@@ -11,17 +11,16 @@ import android.view.KeyEvent;
import
android.view.inputmethod.BaseInputConnection
;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.InputMethodManager
;
import
io.flutter.embedding.engine.systemchannels.TextInputChannel
;
import
io.flutter.plugin.common.ErrorLogResult
;
import
io.flutter.plugin.common.MethodChannel
;
import
io.flutter.view.FlutterView
;
import
java.util.Arrays
;
import
java.util.HashMap
;
class
InputConnectionAdaptor
extends
BaseInputConnection
{
private
final
FlutterView
mFlutterView
;
private
final
int
mClient
;
private
final
MethodChannel
mFlutter
Channel
;
private
final
TextInputChannel
textInput
Channel
;
private
final
Editable
mEditable
;
private
int
mBatchCount
;
private
InputMethodManager
mImm
;
...
...
@@ -29,12 +28,16 @@ class InputConnectionAdaptor extends BaseInputConnection {
private
static
final
MethodChannel
.
Result
logger
=
new
ErrorLogResult
(
"FlutterTextInput"
);
public
InputConnectionAdaptor
(
FlutterView
view
,
int
client
,
MethodChannel
flutterChannel
,
Editable
editable
)
{
public
InputConnectionAdaptor
(
FlutterView
view
,
int
client
,
TextInputChannel
textInputChannel
,
Editable
editable
)
{
super
(
view
,
true
);
mFlutterView
=
view
;
mClient
=
client
;
mFlutterChannel
=
flutter
Channel
;
this
.
textInputChannel
=
textInput
Channel
;
mEditable
=
editable
;
mBatchCount
=
0
;
mImm
=
(
InputMethodManager
)
view
.
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
...
...
@@ -55,14 +58,14 @@ class InputConnectionAdaptor extends BaseInputConnection {
selectionStart
,
selectionEnd
,
composingStart
,
composingEnd
);
HashMap
<
Object
,
Object
>
state
=
new
HashMap
<>();
state
.
put
(
"text"
,
mEditable
.
toString
());
state
.
put
(
"selectionBase"
,
selectionStart
);
state
.
put
(
"selectionExtent"
,
selectionEnd
);
state
.
put
(
"composingBase"
,
composingStart
);
state
.
put
(
"composingExtent"
,
composingEnd
);
mFlutterChannel
.
invokeMethod
(
"TextInputClient.updateEditingState"
,
Arrays
.
asList
(
mClient
,
state
),
logger
);
textInputChannel
.
updateEditingState
(
mClient
,
mEditable
.
toString
(),
selectionStart
,
selectionEnd
,
composingStart
,
composingEnd
);
}
@Override
...
...
@@ -178,39 +181,30 @@ class InputConnectionAdaptor extends BaseInputConnection {
@Override
public
boolean
performEditorAction
(
int
actionCode
)
{
switch
(
actionCode
)
{
// TODO(mattcarroll): is newline an appropriate action for "none"?
case
EditorInfo
.
IME_ACTION_NONE
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.newline"
),
logger
);
textInputChannel
.
newline
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_UNSPECIFIED
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.unspecified"
),
logger
);
textInputChannel
.
unspecifiedAction
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_GO
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.go"
),
logger
);
textInputChannel
.
go
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_SEARCH
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.search"
),
logger
);
textInputChannel
.
search
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_SEND
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.send"
),
logger
);
textInputChannel
.
send
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_NEXT
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.next"
),
logger
);
textInputChannel
.
next
(
mClient
);
break
;
case
EditorInfo
.
IME_ACTION_PREVIOUS
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.previous"
),
logger
);
textInputChannel
.
previous
(
mClient
);
break
;
default
:
case
EditorInfo
.
IME_ACTION_DONE
:
mFlutterChannel
.
invokeMethod
(
"TextInputClient.performAction"
,
Arrays
.
asList
(
mClient
,
"TextInputAction.done"
),
logger
);
textInputChannel
.
done
(
mClient
);
break
;
}
return
true
;
...
...
shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
浏览文件 @
256db4bc
...
...
@@ -5,6 +5,7 @@
package
io.flutter.plugin.editing
;
import
android.content.Context
;
import
android.support.annotation.NonNull
;
import
android.text.Editable
;
import
android.text.InputType
;
import
android.text.Selection
;
...
...
@@ -12,84 +13,87 @@ import android.view.inputmethod.BaseInputConnection;
import
android.view.inputmethod.EditorInfo
;
import
android.view.inputmethod.InputConnection
;
import
android.view.inputmethod.InputMethodManager
;
import
io.flutter.plugin.common.JSONMethodCodec
;
import
io.flutter.plugin.common.MethodCall
;
import
io.flutter.plugin.common.MethodChannel
;
import
io.flutter.plugin.common.MethodChannel.MethodCallHandler
;
import
io.flutter.plugin.common.MethodChannel.Result
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.systemchannels.TextInputChannel
;
import
io.flutter.view.FlutterView
;
import
org.json.JSONArray
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
/**
* Android implementation of the text input plugin.
*/
public
class
TextInputPlugin
implements
MethodCallHandler
{
public
class
TextInputPlugin
{
private
final
FlutterView
mView
;
private
final
InputMethodManager
mImm
;
private
final
MethodChannel
mFlutter
Channel
;
private
final
TextInputChannel
textInput
Channel
;
private
int
mClient
=
0
;
private
JSONObject
mC
onfiguration
;
private
TextInputChannel
.
Configuration
c
onfiguration
;
private
Editable
mEditable
;
private
boolean
mRestartInputPending
;
public
TextInputPlugin
(
FlutterView
view
)
{
public
TextInputPlugin
(
FlutterView
view
,
@NonNull
DartExecutor
dartExecutor
)
{
mView
=
view
;
mImm
=
(
InputMethodManager
)
view
.
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
mFlutterChannel
=
new
MethodChannel
(
view
,
"flutter/textinput"
,
JSONMethodCodec
.
INSTANCE
);
mFlutterChannel
.
setMethodCallHandler
(
this
);
}
textInputChannel
=
new
TextInputChannel
(
dartExecutor
);
textInputChannel
.
setTextInputMethodHandler
(
new
TextInputChannel
.
TextInputMethodHandler
()
{
@Override
public
void
onMethodCall
(
MethodCall
call
,
Result
result
)
{
String
method
=
call
.
method
;
Object
args
=
call
.
arguments
;
try
{
if
(
method
.
equals
(
"TextInput.show"
))
{
public
void
show
()
{
showTextInput
(
mView
);
result
.
success
(
null
);
}
else
if
(
method
.
equals
(
"TextInput.hide"
))
{
}
@Override
public
void
hide
()
{
hideTextInput
(
mView
);
result
.
success
(
null
);
}
else
if
(
method
.
equals
(
"TextInput.setClient"
))
{
final
JSONArray
argumentList
=
(
JSONArray
)
args
;
setTextInputClient
(
mView
,
argumentList
.
getInt
(
0
),
argumentList
.
getJSONObject
(
1
));
result
.
success
(
null
);
}
else
if
(
method
.
equals
(
"TextInput.setEditingState"
))
{
setTextInputEditingState
(
mView
,
(
JSONObject
)
args
);
result
.
success
(
null
);
}
else
if
(
method
.
equals
(
"TextInput.clearClient"
))
{
clearTextInputClient
();
result
.
success
(
null
);
}
else
{
result
.
notImplemented
();
}
}
catch
(
JSONException
e
)
{
result
.
error
(
"error"
,
"JSON error: "
+
e
.
getMessage
(),
null
);
@Override
public
void
setClient
(
int
textInputClientId
,
TextInputChannel
.
Configuration
configuration
)
{
setTextInputClient
(
textInputClientId
,
configuration
);
}
@Override
public
void
setEditingState
(
TextInputChannel
.
TextEditState
editingState
)
{
setTextInputEditingState
(
mView
,
editingState
);
}
@Override
public
void
clearClient
()
{
clearTextInputClient
();
}
});
}
private
static
int
inputTypeFromTextInputType
(
JSONObject
type
,
boolean
obscureText
,
boolean
autocorrect
,
String
textCapitalization
)
throws
JSONException
{
String
inputType
=
type
.
getString
(
"name"
);
if
(
inputType
.
equals
(
"TextInputType.datetime"
))
return
InputType
.
TYPE_CLASS_DATETIME
;
if
(
inputType
.
equals
(
"TextInputType.number"
))
{
private
static
int
inputTypeFromTextInputType
(
TextInputChannel
.
InputType
type
,
boolean
obscureText
,
boolean
autocorrect
,
TextInputChannel
.
TextCapitalization
textCapitalization
)
{
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
DATETIME
)
{
return
InputType
.
TYPE_CLASS_DATETIME
;
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
NUMBER
)
{
int
textType
=
InputType
.
TYPE_CLASS_NUMBER
;
if
(
type
.
optBoolean
(
"signed"
))
textType
|=
InputType
.
TYPE_NUMBER_FLAG_SIGNED
;
if
(
type
.
optBoolean
(
"decimal"
))
textType
|=
InputType
.
TYPE_NUMBER_FLAG_DECIMAL
;
if
(
type
.
isSigned
)
{
textType
|=
InputType
.
TYPE_NUMBER_FLAG_SIGNED
;
}
if
(
type
.
isDecimal
)
{
textType
|=
InputType
.
TYPE_NUMBER_FLAG_DECIMAL
;
}
return
textType
;
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
PHONE
)
{
return
InputType
.
TYPE_CLASS_PHONE
;
}
if
(
inputType
.
equals
(
"TextInputType.phone"
))
return
InputType
.
TYPE_CLASS_PHONE
;
int
textType
=
InputType
.
TYPE_CLASS_TEXT
;
if
(
inputType
.
equals
(
"TextInputType.multiline"
))
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
MULTILINE
)
{
textType
|=
InputType
.
TYPE_TEXT_FLAG_MULTI_LINE
;
else
if
(
inputType
.
equals
(
"TextInputType.emailAddress"
))
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
EMAIL_ADDRESS
)
{
textType
|=
InputType
.
TYPE_TEXT_VARIATION_EMAIL_ADDRESS
;
else
if
(
inputType
.
equals
(
"TextInputType.url"
))
}
else
if
(
type
.
type
==
TextInputChannel
.
TextInputType
.
URL
)
{
textType
|=
InputType
.
TYPE_TEXT_VARIATION_URI
;
}
if
(
obscureText
)
{
// Note: both required. Some devices ignore TYPE_TEXT_FLAG_NO_SUGGESTIONS.
textType
|=
InputType
.
TYPE_TEXT_FLAG_NO_SUGGESTIONS
;
...
...
@@ -97,69 +101,50 @@ public class TextInputPlugin implements MethodCallHandler {
}
else
{
if
(
autocorrect
)
textType
|=
InputType
.
TYPE_TEXT_FLAG_AUTO_CORRECT
;
}
if
(
textCapitalization
.
equals
(
"TextCapitalization.characters"
))
{
if
(
textCapitalization
==
TextInputChannel
.
TextCapitalization
.
CHARACTERS
)
{
textType
|=
InputType
.
TYPE_TEXT_FLAG_CAP_CHARACTERS
;
}
else
if
(
textCapitalization
.
equals
(
"TextCapitalization.words"
)
)
{
}
else
if
(
textCapitalization
==
TextInputChannel
.
TextCapitalization
.
WORDS
)
{
textType
|=
InputType
.
TYPE_TEXT_FLAG_CAP_WORDS
;
}
else
if
(
textCapitalization
.
equals
(
"TextCapitalization.sentences"
)
)
{
}
else
if
(
textCapitalization
==
TextInputChannel
.
TextCapitalization
.
SENTENCES
)
{
textType
|=
InputType
.
TYPE_TEXT_FLAG_CAP_SENTENCES
;
}
return
textType
;
}
private
static
int
inputActionFromTextInputAction
(
String
inputAction
)
{
switch
(
inputAction
)
{
case
"TextInputAction.newline"
:
return
EditorInfo
.
IME_ACTION_NONE
;
case
"TextInputAction.none"
:
return
EditorInfo
.
IME_ACTION_NONE
;
case
"TextInputAction.unspecified"
:
return
EditorInfo
.
IME_ACTION_UNSPECIFIED
;
case
"TextInputAction.done"
:
return
EditorInfo
.
IME_ACTION_DONE
;
case
"TextInputAction.go"
:
return
EditorInfo
.
IME_ACTION_GO
;
case
"TextInputAction.search"
:
return
EditorInfo
.
IME_ACTION_SEARCH
;
case
"TextInputAction.send"
:
return
EditorInfo
.
IME_ACTION_SEND
;
case
"TextInputAction.next"
:
return
EditorInfo
.
IME_ACTION_NEXT
;
case
"TextInputAction.previous"
:
return
EditorInfo
.
IME_ACTION_PREVIOUS
;
default
:
// Present default key if bad input type is given.
return
EditorInfo
.
IME_ACTION_UNSPECIFIED
;
}
}
public
InputConnection
createInputConnection
(
FlutterView
view
,
EditorInfo
outAttrs
)
throws
JSONException
{
public
InputConnection
createInputConnection
(
FlutterView
view
,
EditorInfo
outAttrs
)
{
if
(
mClient
==
0
)
return
null
;
outAttrs
.
inputType
=
inputTypeFromTextInputType
(
mConfiguration
.
getJSONObject
(
"inputType"
),
mConfiguration
.
optBoolean
(
"obscureText"
),
mConfiguration
.
optBoolean
(
"autocorrect"
,
true
),
mConfiguration
.
getString
(
"textCapitalization"
));
outAttrs
.
inputType
=
inputTypeFromTextInputType
(
configuration
.
inputType
,
configuration
.
obscureText
,
configuration
.
autocorrect
,
configuration
.
textCapitalization
);
outAttrs
.
imeOptions
=
EditorInfo
.
IME_FLAG_NO_FULLSCREEN
;
int
enterAction
;
if
(
mConfiguration
.
isNull
(
"inputAction"
)
)
{
if
(
configuration
.
inputAction
==
null
)
{
// If an explicit input action isn't set, then default to none for multi-line fields
// and done for single line fields.
enterAction
=
(
InputType
.
TYPE_TEXT_FLAG_MULTI_LINE
&
outAttrs
.
inputType
)
!=
0
?
EditorInfo
.
IME_ACTION_NONE
:
EditorInfo
.
IME_ACTION_DONE
;
}
else
{
enterAction
=
inputActionFromTextInputAction
(
mConfiguration
.
getString
(
"inputAction"
))
;
enterAction
=
configuration
.
inputAction
;
}
if
(
!
mConfiguration
.
isNull
(
"actionLabel"
)
)
{
outAttrs
.
actionLabel
=
mConfiguration
.
getString
(
"actionLabel"
)
;
if
(
configuration
.
actionLabel
!=
null
)
{
outAttrs
.
actionLabel
=
configuration
.
actionLabel
;
outAttrs
.
actionId
=
enterAction
;
}
outAttrs
.
imeOptions
|=
enterAction
;
InputConnectionAdaptor
connection
=
new
InputConnectionAdaptor
(
view
,
mClient
,
mFlutterChannel
,
mEditable
);
InputConnectionAdaptor
connection
=
new
InputConnectionAdaptor
(
view
,
mClient
,
textInputChannel
,
mEditable
);
outAttrs
.
initialSelStart
=
Selection
.
getSelectionStart
(
mEditable
);
outAttrs
.
initialSelEnd
=
Selection
.
getSelectionEnd
(
mEditable
);
...
...
@@ -175,9 +160,9 @@ public class TextInputPlugin implements MethodCallHandler {
mImm
.
hideSoftInputFromWindow
(
view
.
getApplicationWindowToken
(),
0
);
}
private
void
setTextInputClient
(
FlutterView
view
,
int
client
,
JSONObject
configuration
)
{
private
void
setTextInputClient
(
int
client
,
TextInputChannel
.
Configuration
configuration
)
{
mClient
=
client
;
mC
onfiguration
=
configuration
;
this
.
c
onfiguration
=
configuration
;
mEditable
=
Editable
.
Factory
.
getInstance
().
newEditable
(
""
);
// setTextInputClient will be followed by a call to setTextInputEditingState.
...
...
@@ -185,9 +170,9 @@ public class TextInputPlugin implements MethodCallHandler {
mRestartInputPending
=
true
;
}
private
void
applyStateToSelection
(
JSONObject
state
)
throws
JSONException
{
int
selStart
=
state
.
getInt
(
"selectionBase"
)
;
int
selEnd
=
state
.
getInt
(
"selectionExtent"
)
;
private
void
applyStateToSelection
(
TextInputChannel
.
TextEditState
state
)
{
int
selStart
=
state
.
selectionStart
;
int
selEnd
=
state
.
selectionEnd
;
if
(
selStart
>=
0
&&
selStart
<=
mEditable
.
length
()
&&
selEnd
>=
0
&&
selEnd
<=
mEditable
.
length
())
{
Selection
.
setSelection
(
mEditable
,
selStart
,
selEnd
);
...
...
@@ -196,15 +181,15 @@ public class TextInputPlugin implements MethodCallHandler {
}
}
private
void
setTextInputEditingState
(
FlutterView
view
,
JSONObject
state
)
throws
JSONException
{
if
(!
mRestartInputPending
&&
state
.
getString
(
"text"
)
.
equals
(
mEditable
.
toString
()))
{
private
void
setTextInputEditingState
(
FlutterView
view
,
TextInputChannel
.
TextEditState
state
)
{
if
(!
mRestartInputPending
&&
state
.
text
.
equals
(
mEditable
.
toString
()))
{
applyStateToSelection
(
state
);
mImm
.
updateSelection
(
mView
,
Math
.
max
(
Selection
.
getSelectionStart
(
mEditable
),
0
),
Math
.
max
(
Selection
.
getSelectionEnd
(
mEditable
),
0
),
BaseInputConnection
.
getComposingSpanStart
(
mEditable
),
BaseInputConnection
.
getComposingSpanEnd
(
mEditable
));
}
else
{
mEditable
.
replace
(
0
,
mEditable
.
length
(),
state
.
getString
(
"text"
)
);
mEditable
.
replace
(
0
,
mEditable
.
length
(),
state
.
text
);
applyStateToSelection
(
state
);
mImm
.
restartInput
(
view
);
mRestartInputPending
=
false
;
...
...
shell/platform/android/io/flutter/plugin/platform/PlatformPlugin.java
浏览文件 @
256db4bc
此差异已折叠。
点击以展开。
shell/platform/android/io/flutter/view/AccessibilityBridge.java
浏览文件 @
256db4bc
此差异已折叠。
点击以展开。
shell/platform/android/io/flutter/view/FlutterView.java
浏览文件 @
256db4bc
...
...
@@ -15,6 +15,7 @@ import android.graphics.SurfaceTexture;
import
android.net.Uri
;
import
android.os.Build
;
import
android.os.Handler
;
import
android.os.LocaleList
;
import
android.provider.Settings
;
import
android.text.format.DateFormat
;
import
android.util.AttributeSet
;
...
...
@@ -29,17 +30,17 @@ import io.flutter.app.FlutterPluginRegistry;
import
io.flutter.embedding.engine.FlutterJNI
;
import
io.flutter.embedding.engine.android.AndroidKeyProcessor
;
import
io.flutter.embedding.engine.dart.DartExecutor
;
import
io.flutter.embedding.engine.systemchannels.AccessibilityChannel
;
import
io.flutter.embedding.engine.systemchannels.KeyEventChannel
;
import
io.flutter.embedding.engine.systemchannels.LifecycleChannel
;
import
io.flutter.embedding.engine.systemchannels.NavigationChannel
;
import
io.flutter.embedding.engine.systemchannels.PlatformChannel
;
import
io.flutter.embedding.engine.systemchannels.SettingsChannel
;
import
io.flutter.embedding.engine.systemchannels.SystemChannel
;
import
io.flutter.plugin.common.*
;
import
io.flutter.plugin.editing.TextInputPlugin
;
import
io.flutter.plugin.platform.PlatformPlugin
;
import
org.json.JSONException
;
import
java.lang.reflect.Method
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
import
java.util.*
;
...
...
@@ -87,18 +88,21 @@ public class FlutterView extends SurfaceView
}
private
final
DartExecutor
dartExecutor
;
private
final
AccessibilityChannel
accessibilityChannel
;
private
final
NavigationChannel
navigationChannel
;
private
final
KeyEventChannel
keyEventChannel
;
private
final
LifecycleChannel
lifecycleChannel
;
private
final
LocalizationChannel
localizationChannel
;
private
final
PlatformChannel
platformChannel
;
private
final
SettingsChannel
settingsChannel
;
private
final
SystemChannel
systemChannel
;
private
final
InputMethodManager
mImm
;
private
final
TextInputPlugin
mTextInputPlugin
;
private
final
AndroidKeyProcessor
androidKeyProcessor
;
private
AccessibilityBridge
mAccessibilityNodeProvider
;
private
final
SurfaceHolder
.
Callback
mSurfaceCallback
;
private
final
ViewportMetrics
mMetrics
;
private
final
AccessibilityManager
mAccessibilityManager
;
private
final
MethodChannel
mFlutterLocalizationChannel
;
private
final
List
<
ActivityLifecycleListener
>
mActivityLifecycleListeners
;
private
final
List
<
FirstFrameListener
>
mFirstFrameListeners
;
private
final
AtomicLong
nextTextureId
=
new
AtomicLong
(
0L
);
...
...
@@ -160,23 +164,25 @@ public class FlutterView extends SurfaceView
mActivityLifecycleListeners
=
new
ArrayList
<>();
mFirstFrameListeners
=
new
ArrayList
<>();
// Configure the platform plugins and flutter channels.
// Create all platform channels
accessibilityChannel
=
new
AccessibilityChannel
(
dartExecutor
);
navigationChannel
=
new
NavigationChannel
(
dartExecutor
);
keyEventChannel
=
new
KeyEventChannel
(
dartExecutor
);
lifecycleChannel
=
new
LifecycleChannel
(
dartExecutor
);
localizationChannel
=
new
LocalizationChannel
(
dartExecutor
);
platformChannel
=
new
PlatformChannel
(
dartExecutor
);
systemChannel
=
new
SystemChannel
(
dartExecutor
);
settingsChannel
=
new
SettingsChannel
(
dartExecutor
);
mFlutterLocalizationChannel
=
new
MethodChannel
(
this
,
"flutter/localization"
,
JSONMethodCodec
.
INSTANCE
);
PlatformPlugin
platformPlugin
=
new
PlatformPlugin
(
activity
);
MethodChannel
flutterPlatformChannel
=
new
MethodChannel
(
this
,
"flutter/platform"
,
JSONMethodCodec
.
INSTANCE
);
flutterPlatformChannel
.
setMethodCallHandler
(
platformPlugin
);
// Create and setup plugins
PlatformPlugin
platformPlugin
=
new
PlatformPlugin
(
activity
,
platformChannel
);
addActivityLifecycleListener
(
platformPlugin
);
mImm
=
(
InputMethodManager
)
getContext
().
getSystemService
(
Context
.
INPUT_METHOD_SERVICE
);
mTextInputPlugin
=
new
TextInputPlugin
(
this
);
mTextInputPlugin
=
new
TextInputPlugin
(
this
,
dartExecutor
);
androidKeyProcessor
=
new
AndroidKeyProcessor
(
keyEventChannel
);
setLocales
(
getResources
().
getConfiguration
());
// Send initial platform information to Dart
sendLocalesToDart
(
getResources
().
getConfiguration
());
sendUserPlatformSettingsToDart
();
}
...
...
@@ -311,39 +317,21 @@ public class FlutterView extends SurfaceView
.
send
();
}
private
void
setLocales
(
Configuration
config
)
{
if
(
Build
.
VERSION
.
SDK_INT
>=
24
)
{
try
{
// Passes the full list of locales for android API >= 24 with reflection.
Object
localeList
=
config
.
getClass
().
getDeclaredMethod
(
"getLocales"
).
invoke
(
config
);
Method
localeListGet
=
localeList
.
getClass
().
getDeclaredMethod
(
"get"
,
int
.
class
);
Method
localeListSize
=
localeList
.
getClass
().
getDeclaredMethod
(
"size"
);
int
localeCount
=
(
int
)
localeListSize
.
invoke
(
localeList
);
List
<
String
>
data
=
new
ArrayList
<>();
private
void
sendLocalesToDart
(
Configuration
config
)
{
LocaleList
localeList
=
config
.
getLocales
();
int
localeCount
=
localeList
.
size
();
List
<
Locale
>
locales
=
new
ArrayList
<>();
for
(
int
index
=
0
;
index
<
localeCount
;
++
index
)
{
Locale
locale
=
(
Locale
)
localeListGet
.
invoke
(
localeList
,
index
);
data
.
add
(
locale
.
getLanguage
());
data
.
add
(
locale
.
getCountry
());
data
.
add
(
locale
.
getScript
());
data
.
add
(
locale
.
getVariant
());
}
mFlutterLocalizationChannel
.
invokeMethod
(
"setLocale"
,
data
);
return
;
}
catch
(
Exception
exception
)
{
// Any exception is a failure. Resort to fallback of sending only one locale.
}
Locale
locale
=
localeList
.
get
(
index
);
locales
.
add
(
locale
);
}
// Fallback single locale passing for android API < 24. Should work always.
@SuppressWarnings
(
"deprecation"
)
Locale
locale
=
config
.
locale
;
// getScript() is gated because it is added in API 21.
mFlutterLocalizationChannel
.
invokeMethod
(
"setLocale"
,
Arrays
.
asList
(
locale
.
getLanguage
(),
locale
.
getCountry
(),
Build
.
VERSION
.
SDK_INT
>=
21
?
locale
.
getScript
()
:
""
,
locale
.
getVariant
()));
localizationChannel
.
sendLocales
(
locales
);
}
@Override
protected
void
onConfigurationChanged
(
Configuration
newConfig
)
{
super
.
onConfigurationChanged
(
newConfig
);
se
tLocales
(
newConfig
);
se
ndLocalesToDart
(
newConfig
);
sendUserPlatformSettingsToDart
();
}
...
...
@@ -374,13 +362,7 @@ public class FlutterView extends SurfaceView
@Override
public
InputConnection
onCreateInputConnection
(
EditorInfo
outAttrs
)
{
try
{
mLastInputConnection
=
mTextInputPlugin
.
createInputConnection
(
this
,
outAttrs
);
return
mLastInputConnection
;
}
catch
(
JSONException
e
)
{
Log
.
e
(
TAG
,
"Failed to create input connection"
,
e
);
return
null
;
}
return
mTextInputPlugin
.
createInputConnection
(
this
,
outAttrs
);
}
// Must match the PointerChange enum in pointer.dart.
...
...
@@ -1006,14 +988,12 @@ public class FlutterView extends SurfaceView
return
null
;
}
private
AccessibilityBridge
mAccessibilityNodeProvider
;
void
ensureAccessibilityEnabled
()
{
if
(!
isAttached
())
return
;
mAccessibilityEnabled
=
true
;
if
(
mAccessibilityNodeProvider
==
null
)
{
mAccessibilityNodeProvider
=
new
AccessibilityBridge
(
this
);
mAccessibilityNodeProvider
=
new
AccessibilityBridge
(
this
,
accessibilityChannel
);
}
mNativeView
.
getFlutterJNI
().
setSemanticsEnabled
(
true
);
mAccessibilityNodeProvider
.
setAccessibilityEnabled
(
true
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录