IBinder 实现
1、Service
publicclassFloatTextServiceextendsService{privateTextViewtvFloat;privateWindowManagerwindowManager;privatefinalIBinderbinder=newFloatTextServiceBinder();publicclassFloatTextServiceBinderextendsBinder{publicFloatTextServicegetService(){returnFloatTextService.this;}}@Nullable@OverridepublicIBinderonBind(Intentintent){returnbinder;}@OverridepublicvoidonCreate(){super.onCreate();windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);// 创建布局参数WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);// 设置位置为左下角params.gravity=Gravity.BOTTOM|Gravity.START;params.x=0;params.y=0;LayoutInflaterinflater=LayoutInflater.from(this);tvFloat=(TextView)inflater.inflate(R.layout.float_text,null);// 添加到窗口windowManager.addView(tvFloat,params);}publicvoidshowFloatText(Stringtext){tvFloat.setText(text);}@OverridepublicvoidonDestroy(){super.onDestroy();if(tvFloat!=null){windowManager.removeView(tvFloat);}}}
<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/tv_float"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="12dp"android:textSize="14sp"/>
2、Manifest
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/><application>...<serviceandroid:name=".viewfixed.service.FloatTextService"android:enabled="true"android:exported="false"/></application>
3、Activity Layout
- activity_float_text_service_test.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".viewfixed.FloatTextServiceTestActivity"><Buttonandroid:id="@+id/btn_show_float_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="显示悬浮文本"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- FloatTextServiceTestActivity.java
publicclassFloatTextServiceTestActivityextendsAppCompatActivity{privateActivityResultLauncher<Intent>floatPermissionLauncher;privateFloatTextServicefloatTextService;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_float_text_service_test);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});test();}privatevoidtest(){floatPermissionLauncher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(checkFloatPermission()){createFloatText();}else{Toast.makeText(this,"未开启浮窗权限",Toast.LENGTH_SHORT).show();}});if(checkFloatPermission()){createFloatText();}else{requestFloatPermission();}ButtonbtnShowFloatText=findViewById(R.id.btn_show_float_text);btnShowFloatText.setOnClickListener(v->{floatTextService.showFloatText("Hello Float Text");});}privatebooleancheckFloatPermission(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){returnSettings.canDrawOverlays(this);}returntrue;}privatevoidrequestFloatPermission(){Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:"+getPackageName()));floatPermissionLauncher.launch(intent);}privatevoidcreateFloatText(){bindService(newIntent(this,FloatTextService.class),newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamecomponentName,IBinderiBinder){FloatTextService.FloatTextServiceBinderbinder=(FloatTextService.FloatTextServiceBinder)iBinder;floatTextService=binder.getService();}@OverridepublicvoidonServiceDisconnected(ComponentNamecomponentName){}},BIND_AUTO_CREATE);}}
BroadcastReceiver 实现
1、Service
publicclassFloatTextServiceextendsService{privateTextViewtvFloat;privateWindowManagerwindowManager;privatefinalIBinderbinder=newFloatTextServiceBinder();publicclassFloatTextServiceBinderextendsBinder{publicFloatTextServicegetService(){returnFloatTextService.this;}}publicstaticfinalStringACTION="SHOW_FLOAT_TEXT";privateBroadcastReceiverFloatTextServiceBroadcastReceiver;@Nullable@OverridepublicIBinderonBind(Intentintent){returnbinder;}@OverridepublicvoidonCreate(){super.onCreate();windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);// 创建布局参数WindowManager.LayoutParamsparams=newWindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT,WindowManager.LayoutParams.WRAP_CONTENT,Build.VERSION.SDK_INT>=Build.VERSION_CODES.O?WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY:WindowManager.LayoutParams.TYPE_PHONE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,PixelFormat.TRANSLUCENT);// 设置位置为左下角params.gravity=Gravity.BOTTOM|Gravity.START;params.x=0;params.y=0;LayoutInflaterinflater=LayoutInflater.from(this);tvFloat=(TextView)inflater.inflate(R.layout.float_text,null);// 添加到窗口windowManager.addView(tvFloat,params);FloatTextServiceBroadcastReceiver=newBroadcastReceiver(){@OverridepublicvoidonReceive(Contextcontext,Intentintent){if(intent.hasExtra("text")){StringnewText=intent.getStringExtra("text");tvFloat.setText(newText);}}};IntentFilterintentFilter=newIntentFilter();intentFilter.addAction(ACTION);registerReceiver(FloatTextServiceBroadcastReceiver,intentFilter);}publicvoidshowFloatText(Stringtext){tvFloat.setText(text);}@OverridepublicvoidonDestroy(){super.onDestroy();if(tvFloat!=null){windowManager.removeView(tvFloat);}}}
<?xml version="1.0" encoding="utf-8"?><TextViewxmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/tv_float"android:layout_width="wrap_content"android:layout_height="wrap_content"android:padding="12dp"android:textSize="14sp"/>
2、Manifest
<uses-permissionandroid:name="android.permission.SYSTEM_ALERT_WINDOW"/><application>...<serviceandroid:name=".viewfixed.service.FloatTextService"android:enabled="true"android:exported="false"/></application>
3、Activity Layout
- activity_float_text_service_test.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".viewfixed.FloatTextServiceTestActivity"><Buttonandroid:id="@+id/btn_show_float_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="显示悬浮文本"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"/></androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- FloatTextServiceTestActivity.java
publicclassFloatTextServiceTestActivityextendsAppCompatActivity{privateActivityResultLauncher<Intent>floatPermissionLauncher;privateFloatTextServicefloatTextService;@OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_float_text_service_test);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v,insets)->{InsetssystemBars=insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left,systemBars.top,systemBars.right,systemBars.bottom);returninsets;});test();}privatebooleancheckFloatPermission(){if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){returnSettings.canDrawOverlays(this);}returntrue;}privatevoidrequestFloatPermission(){Intentintent=newIntent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:"+getPackageName()));floatPermissionLauncher.launch(intent);}privatevoidcreateFloatText(){bindService(newIntent(this,FloatTextService.class),newServiceConnection(){@OverridepublicvoidonServiceConnected(ComponentNamecomponentName,IBinderiBinder){FloatTextService.FloatTextServiceBinderbinder=(FloatTextService.FloatTextServiceBinder)iBinder;floatTextService=binder.getService();}@OverridepublicvoidonServiceDisconnected(ComponentNamecomponentName){}},BIND_AUTO_CREATE);}privatevoidtest(){floatPermissionLauncher=registerForActivityResult(newActivityResultContracts.StartActivityForResult(),result->{if(checkFloatPermission()){createFloatText();}else{Toast.makeText(this,"未开启浮窗权限",Toast.LENGTH_SHORT).show();}});if(checkFloatPermission()){createFloatText();}else{requestFloatPermission();}ButtonbtnShowFloatText=findViewById(R.id.btn_show_float_text);btnShowFloatText.setOnClickListener(v->{Intentintent=newIntent(FloatTextService.ACTION);intent.putExtra("text","Hello Float Text");sendBroadcast(intent);});}}