I tried to make floating widget overlay button - like messenger profile photo widget, which is displayed when someone send you message. I used these files. When I run program, there is nothing invalid in code. I see app with button but there is nothing visible after click.
我试着让浮动的小部件覆盖在按钮上,就像Messenger个人资料照片小部件一样,当有人给你发消息时就会显示出来。我用了这些文件。当我运行程序时,代码中没有任何无效的东西。我看到了带按钮的应用程序,但点击后什么都看不到。
MainActivity.java:
MainActivity.java:
package com.example.mywidget;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startFloatingWidgetService();
};
private void startFloatingWidgetService() {
Intent intent = new Intent(this, FloatingWidgetService.class);
startService(intent);
}
};
FloatingWidgetService.java
FloatingWidgetService.java
package com.example.mywidget;
import android.app.Service;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
public class FloatingWidgetService extends Service {
private WindowManager mWindowManager;
private View mFloatingWidgetView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
mFloatingWidgetView = LayoutInflater.from(this).inflate(R.layout.floating_widget_layout, null);
// Inicializace tlačítka
Button button = mFloatingWidgetView.findViewById(R.id.floating_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showTextDialog();
}
});
// Inicializace WindowManager
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
params.gravity = Gravity.BOTTOM | Gravity.END;
mWindowManager.addView(mFloatingWidgetView, params);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFloatingWidgetView != null && mWindowManager != null) {
mWindowManager.removeView(mFloatingWidgetView);
}
}
private void showTextDialog() {
}
}
activity_main.xml
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns: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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Start Floating Widget Service" />
</androidx.constraintlayout.widget.ConstraintLayout>
floating_widget_layout.xml
浮动_窗口小部件_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/floating_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="dfdsfdasdfasdfAFASD"
android:layout_gravity="end"
android:background="@android:color/holo_red_light"/>
</LinearLayout>
AndroidManifest.xml
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.Mywidget"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
更多回答
I have done some modification in your files. This code works fine when i tested it on my physical device, but it has one drawback that when user granted the permission of overlay it do not show floating widget but when you relaunch the app then it show the flaoting button. if you want to achieve this when user granted permission and it should show the flaoting widget immediately after it you can do it by imlementing broadcast receiver (with permission of MANAGE_OVERLAY_PERMISSION") and using the foregroundservice: however the code is this:
我对你的档案做了一些修改。当我在我的物理设备上测试它时,这个代码运行得很好,但它有一个缺点,当用户被授予覆盖权限时,它不会显示浮动窗口小部件,但当你重新启动应用程序时,它会显示闪烁按钮。如果您想在用户授予权限时实现这一点,并且它应该在它之后立即显示Flotting小部件,您可以通过实现广播接收器(具有Manage_OVERLAY_PERMISSION“的权限)并使用前台服务来实现这一点:然而,代码如下:
MainActivity.java:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startFloatingWidgetService();
}
private void startFloatingWidgetService() {
Intent intent = new Intent(this, FloatingWidgetService.class);
startService(intent);
}
}
FloatingWidgetService.java
FloatingWidgetService.java
In this class the main change i did is to check if we have permission to overlay or not. if not request permission if it's already give or not needed then show widget.
在这门课上,我所做的主要改变是检查我们是否有覆盖的许可。如果没有请求许可,如果已经给予或不需要许可,则显示Widget。
public class FloatingWidgetService extends Service {
private WindowManager mWindowManager;
private View mFloatingWidgetView;
@Override
public IBinder onBind(Intent intent) {
return null;
}
// Method to request the SYSTEM_ALERT_WINDOW permission
private void requestOverlayPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
// Method to create the floating widget
private void createFloatingWidget() {
// Inflate the layout for the floating widget
mFloatingWidgetView = LayoutInflater.from(this).inflate(R.layout.floating_widget_layout,
null);
// Initialize the button on the floating widget
Button button = mFloatingWidgetView.findViewById(R.id.floating_button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Handle the button click event
showTextDialog();
// You can perform other actions here as needed
}
});
// Initialize the WindowManager
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// Set up WindowManager.LayoutParams for the floating widget
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
);
// Set the gravity of the floating widget (position on the screen)
params.gravity = Gravity.BOTTOM | Gravity.END;
// Add the floating widget to the WindowManager
mWindowManager.addView(mFloatingWidgetView, params);
}
@Override
public void onCreate() {
super.onCreate();
// Check if the permission is granted (only for API level 23 and higher)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
// You don't have permission to draw overlays, so request it
requestOverlayPermission();
} else {
// Permission is granted, proceed with creating the floating widget
createFloatingWidget();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mFloatingWidgetView != null && mWindowManager != null) {
mWindowManager.removeView(mFloatingWidgetView);
}
}
private void showTextDialog() {
}
}
activity_main.xml
Activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns: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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/start_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/start_floating_widget_service"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
floating_widget_layout.xml
浮动_窗口小部件_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/floating_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:background="@android:color/holo_red_light"
android:text="@string/floating_widget_button"
android:textColor="#212121" />
</LinearLayout>
AndroidManifest.xml
AndroidManifest.xml
In your manifest you didn't added service in your manifest.
在您的清单中,您没有在清单中添加服务。
<service
android:name=".FloatingWidgetService"
android:enabled="true"
android:exported="true" />
if you don't face any issue with the overlay permission then it should work by only adding service to your manifest but to be on the safe side add the code that I provided in the FloatingWidgetService class to verify the permission.
如果您没有遇到覆盖权限的任何问题,那么它应该只需向您的清单添加服务,但为了安全起见,请添加我在FloatingWidgetService类中提供的代码来验证权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.FloatingWidget"
tools:targetApi="31">
<service
android:name=".FloatingWidgetService"
android:enabled="true"
android:exported="true" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
You can access the code here : Github
您可以在此处访问代码:GitHub
let me know if it works for you or not.
让我知道它对你是否有效。
Your showTextDialog() method in FloatingWidgetService.java is empty and that's why nothing appears when you call this empty method:
FloatingWidgetService.java中的showTextDialog()方法为空,这就是调用此空方法时不显示任何内容的原因:
private void showTextDialog() {
}
try this to test if it is properly working or not and then replace it with your code you want:
尝试此操作以测试它是否正常工作,然后将其替换为您想要的代码:
private void showTextDialog() {
Toast.makeText(this, "Button clicked!", Toast.LENGTH_SHORT).show();
}
更多回答
Yes, it works, thank you. The problem that there is required second app start is only for first time when you allow permissions to apps, right?
是的,它起作用了,谢谢。问题是,只有当你允许应用程序的权限时,才需要第二次启动应用程序,对吗?
Yes, once permission is granted it will show floating widget and perform other actions on it accordingly how you control it.
是的,一旦被授予权限,它将显示浮动窗口小部件,并根据您的控制方式对其执行其他操作。
Yes, you are right but that is not important in this time because I need to see floating widget button at first, then I can click and see text dialog.
是的,你是对的,但现在这并不重要,因为我需要首先看到浮动的小工具按钮,然后我才能点击并看到文本对话框。
@Mirek check the second answer i posted
@Mirek查看我发布的第二个答案
我是一名优秀的程序员,十分优秀!