如何讓Flutter程序能夠跨應用的更改其餘應用的狀態呢,先看原生如何實現,其次再用MethodChannel對接Flutter就好了,因此此篇更多的是安卓原生開發的知識,提到原生開發跨應用發送消息或者更改狀態,有兩個東西可以實現這樣的需求,一個是ContentObserver,另外一個就是Broadcastjava
ContentObserver被稱爲安卓的內容觀察者,目的是觀察特定Uri引發的數據變化,例如經過一個key(String)來監聽這個key對應值的變化,若是該值發生了變化,那麼整個系統中全部對這個key作了監聽的地方都能知道它被更改了,從而來根據這個key對應的新的值來刷新相關Widget的狀態,這些值都被保存在了/data/system/users/0/下的settings_global.xml,settings_system.xml,settings_secure.xml,分別對應三種不一樣類型的key,android
class MyObserver extends ContentObserver {
final Handler mHandler;
final Context mContext;
public MyObserver(Context context,Handler handler) {
super(handler);
this.mHandler=handler;
this.mContext=context;
}
@Override//重寫ContentObserver的onChange方法
public void onChange(boolean z) {
//此方法當監聽的值改變後會觸發,這裏將消息發送給一個Handler處理
Message obtainMessage=mHandler.obainMessage();//
obtainMessage.obj=System.getString(mContext.getContentResolver(),"Nightmare_Test_Key"));
//拿到Nightmare_Text_Key的新值並將它發送給Handler處理
mHandler.sedMessage(obtainMessage);
}
}
複製代碼
class MyHandler extends Handler {
final TextView mTextView;
MyHandler(TextView view) {
this.mTextView = view;
}
@Override
public void handleMessage(Message message) {
String str = (String) message.obj;//ContentObserver那邊傳過來的值
this.mTextView.setText(TextUtils.isEmpty(str) ? "未獲取到數據" : str);
}
}
複製代碼
TextView mTextView=new TextView(this);
Handler mHandler = new MyHandler(mTextView);
ContentObserver mContextObserser=new MyObserver(this,mHandler);
this.getContentResolver().registerContentObserver(System.getUriFor("Nightmare_Test_Key"),false,mContextObserser);
//第二個參數false表示精準匹配,即值匹配該Uri
複製代碼
System.putString(this.getContentReslover(),"Nightmare_Test_Key","我想把Text的內容改爲這個");
複製代碼
只要註冊了監聽的那個App還在運行,其中的那個TextView的內容就會被更改 #Broadcast Broadcast做爲安卓四大組件之一,其做用也是至關的強大,具體就不詳細闡述,有點相似於EventBus,但安卓的Broadcast能夠貫穿安卓全部在運行的App,那麼咱們怎麼用Broadcast來實現跨應用更新狀態呢?安全
class MyBroadcastReceiver extends BroadcastReceiver{
final TextView mView;
public MyBroadcastReceiver(TextView v){
this.mView=v;
}
@Override
public void onReceive(Context context, Intent intent) {
String result = intent.getStringExtra("Test_Key") ;
this.mView.setText(result);
}
}
複製代碼
TextView mTextView=new TextView(this);
BroadcastReceiver mBroadcastReceiver = new MyBroadcastReceiver(mTextView);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("test.android.intent.action.TEST");
this.registerReceiver(broadcastReceiver,intentFilter);
複製代碼
Intent intent = new Intent();
intent.putExtra("Test_Key","來自其餘應用的消息");
intent.setAction("test.android.intent.action.TEST");
//使用bundle傳遞參數
sendBroadcast(intent);
複製代碼
不是說Flutter嗎? bash
如下的Example就不用ContentObserver了,使用Broadcast,直接上代碼,嘿嘿嘿😜class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
MethodChannel(flutterView, "Nightmare").setMethodCallHandler { call, _ ->
val intent = Intent()
intent.putExtra("Test_Key",call.method)
intent.action = "test.android.intent.action.TEST"
sendBroadcast(intent)
}
}
}
複製代碼
怎麼又是Kotlin了? app
我也不想半路換Kotlin,新建這個Example就是了,不過看起來比Java要簡潔多了 ####Dart部分class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
MethodChannel _channel=MethodChannel("Nightmare");
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("添加一個按鈕"),
onPressed: (){
_channel.invokeMethod("Button");
},
),
RaisedButton(
child: Text("添加一個Card"),
onPressed: (){
_channel.invokeMethod("Card");
},
),
TextField(
onSubmitted: (str){
_channel.invokeMethod(str);
},
)
],
),
),
);
}
}
複製代碼
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
val methodChannel = MethodChannel(flutterView, "Nightmare")
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val result = intent.getStringExtra("Test_Key")
methodChannel.invokeMethod(result,"")
}
}
val mBroadcastReceiver = MyBroadcastReceiver()
val intentFilter = IntentFilter()
intentFilter.addAction("test.android.intent.action.TEST")
this.registerReceiver(mBroadcastReceiver, intentFilter)
}
}
複製代碼
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Widget> _list = [];
MethodChannel platform = MethodChannel("Nightmare");
@override
void initState() {
super.initState();
platform.setMethodCallHandler(platformCallHandler);
}
Future<dynamic> platformCallHandler(MethodCall call) async {
print(call.method);
switch (call.method) {
case "Button":
_list.add(
RaisedButton(
onPressed: () {},
child: Text("按鈕"),
),
);
setState(() {});
break;
case "Card":
_list.add(
Card(
child: Text("Card"),
)
);
setState(() {});
break;
default:
_list.add(
Text(call.method)
);
setState(() {});
break;
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: Center(
child: Column(
children: _list,
),
),
);
}
}
複製代碼