import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setTitle("标题")
.setMessage("内容")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this,"我知道了",Toast.LENGTH_SHORT).show();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this,"取消",Toast.LENGTH_SHORT).show();
}
})
.create();
alertDialog.show();
}
}
此方案的实现是基于 Android 8.1.0,自从Android 6.0 以后,Google 就对一些敏感权限做了收敛,因此我们在系统弹框的时候就需要进行判断。
private void justShowDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext()) //这里去获取上下文
.setIcon(android.R.drawable.ic_dialog_info)
.setTitle("在此处定义标题")
.setMessage("此处定义内容")
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
})
.setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
});
AlertDialog dialog = builder.create();
dialog.setCancelable(false);
dialog.setCanceledOnTouchOutside(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY));
}else {
dialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
}
dialog.show(); //最核心一就是展示
}
如果没有最后的 dialog.show 那自定义的dialog是无法弹出来的。
在service如何使用
在上面我们定义号之后,下面我们就去使用它。
private final Handler mSpHandler;
mSpHandler.post(new Runnable() {
@Override
public void run() {
justShowDialog();
}
});
这样我们一个系统级的dialog就在service中实现了,不过它是一直在弹框,如果想定时去弹框,可以根据自己的时间去修改。
首先在你需要系统dialog的路径下面定义一个dialog文件
然后去实现相关的内容
自定义文件
package com.android.server.storage;
import android.app.AlertDialog;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemProperties;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Gravity;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.TextView;
import android.util.Log;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.os.Handler;
import android.os.Message;
/**
* Created by Administrator on 2022/3/3.
*/
public abstract class SpaceCleanDialog extends AlertDialog implements View.OnClickListener {
private static final int GONE_TIPS = 1;
private static final int TIP_SHOW_TIMES = 3000; // 3s
public Context mContext;
private Button PositiveButton,NegativeButton;
private String text_content;
private RelativeLayout shutdown_tips;
private boolean allowPowerOff = true;
private Button btn_spaceclean,btn_cancel;
private TextView tv_spaceclean_low,tv_spaceclean_full;
protected SpaceCleanDialog(Context context ,String text) {
//frameworks\base\core\res\res\values\styles
super(context,com.android.internal.R.style.TipDialogStyle);
mContext = context;
getWindow().setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
);
WindowManager.LayoutParams attrs = getWindow().getAttributes();
// attrs.alpha=0.85f;
// attrs.dimAmount = 1f;
attrs.setTitle("shutDownDialogWindow");
DisplayMetrics dm = new DisplayMetrics();
dm = mContext.getResources().getDisplayMetrics();
attrs.width = dm.widthPixels; //设置宽度
attrs.height = dm.heightPixels; //设置宽度
getWindow().setAttributes(attrs);
text_content = text;
}
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState); //保存activity的状态
allowPowerOff = SystemProperties.getBoolean("persist.sys.allowpoweroff", true);
Log.d("ShutdownDialog", "onCreate: allowPowerOff="+allowPowerOff);
//调用dialog时 传进来的
if(text_content != null){
Log.d("wfsisxtc", "text_content is :"+text_content);
setContentView(com.android.internal.R.layout.dialog_spaceclean);
btn_spaceclean = (Button)findViewById(com.android.internal.R.id.dialog_btn_spaceclean);
btn_cancel = (Button)findViewById(com.android.internal.R.id.dialog_btn_cancel);
tv_spaceclean_low = (TextView)findViewById(com.android.internal.R.id.tv_spaceclean_low);
tv_spaceclean_full = (TextView)findViewById(com.android.internal.R.id.tv_spaceclean_full);
btn_spaceclean.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
if(text_content.equals("Full_Space")) {
btn_cancel.setVisibility(View.GONE);
tv_spaceclean_low.setVisibility(View.GONE);
tv_spaceclean_full.setVisibility(View.VISIBLE);
} else {
btn_cancel.setVisibility(View.VISIBLE);
tv_spaceclean_low.setVisibility(View.VISIBLE);
tv_spaceclean_full.setVisibility(View.GONE);
}
}
}
public abstract void clickCallBack(View view);
public abstract void dismissCallBack(View view);
/**
*
*
* @param width
* @param height
*/
public void setDialogSize(int width, int height) {
WindowManager.LayoutParams params = getWindow().getAttributes();
params.width = width;
params.height = height;
this.getWindow().setAttributes(params);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case GONE_TIPS:
break;
}
}
};
@Override
public void dismiss() {
super.dismiss();
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case com.android.internal.R.id.dialog_btn_spaceclean:
//前往清理
clickCallBack(view);
//dismiss();
break;
case com.android.internal.R.id.dialog_btn_cancel:
//取消
dismissCallBack(view);
dismiss();
break;
}
}
public void setPositiveButton(int resId, OnClickListener onClick) {
setButton(BUTTON_POSITIVE, mContext.getString(resId), onClick);
}
public void setNegativeButton(int resId, OnClickListener onClick) {
setButton(BUTTON_NEGATIVE, mContext.getString(resId), onClick);
}
}
布局文件
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
android:id="@+id/rl_dialog_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="温馨提示"
android:layout_marginTop="6dp"
android:textSize="24sp"
android:gravity="center"/>
<TextView
android:id="@+id/tv_spaceclean_low"
android:layout_width="149dp"
android:layout_height="77dp"
android:layout_marginTop="9dp"
android:layout_marginLeft="12dp"
android:textSize="15sp"
android:gravity="left"
android:visibility="visible"
android:text="@string/space_clean" />
<TextView
android:id="@+id/tv_spaceclean_full"
android:layout_width="149dp"
android:layout_height="77dp"
android:layout_marginTop="9dp"
android:layout_marginLeft="12dp"
android:textSize="15sp"
android:gravity="left"
android:visibility="gone"
android:text="@string/space_clean_full" />
<Button
android:id="@+id/dialog_btn_spaceclean"
android:layout_width="150dp"
android:layout_height="40dp"
android:layout_marginTop="14dp"
android:layout_marginLeft="5dp"
android:textSize="17sp"
android:background="@drawable/bg_dialog_spaceclean"
android:text="@string/gotospace"/>
<Button
android:id="@+id/dialog_btn_cancel"
android:layout_width="150dp"
android:layout_height="40dp"
android:layout_marginTop="3dp"
android:layout_marginLeft="5dp"
android:textSize="17sp"
android:background="@drawable/bg_dialog_cancel"
android:visibility="visible"
android:text="@string/nexttime"/>
</LinearLayout>
</ScrollView>
当然定义的这些命名 都需要在系统文件去添加。
以及在service中如何使用:
把它封装成一个函数,减少耦合性,方便其他文件去调用。
private static String fullspaceButtonText = "Full_Space";
private static class CloseDialogReceiver extends BroadcastReceiver
implements DialogInterface.OnDismissListener {
private Context mContext;
public Dialog dialog;
CloseDialogReceiver(Context context) {
mContext = context;
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(this, filter);
}
@Override
public void onReceive(Context context, Intent intent) {
dialog.cancel();
}
public void onDismiss(DialogInterface unused) {
mContext.unregisterReceiver(this);
}
}
private void scheduledSpaceClean(String text) {
final StorageManager storage = getContext().getSystemService(StorageManager.class);
final CloseDialogReceiver closer = new CloseDialogReceiver(getContext());
for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
if(scdialog != null)
{
scdialog.dismiss();
}
final File file = vol.getPath();
final UUID uuid = StorageManager.convert(vol.getFsUuid());
final State state = findOrCreateState(uuid);
//这里传入的是上下文,和想要修改时区分的参数
SpaceCleanDialog spacecleanDialog = new SpaceCleanDialog(getContext(),text) {
@Override
public void clickCallBack(View view) {
switch (view.getId()){
case com.android.internal.R.id.dialog_btn_spaceclean:
Slog.v(TAG, "go to clean up>>>>>>>>>>");
Intent intent = new Intent("android.intent.action.fullMem.xtc");
intent.putExtra("memory", state.lastUsableBytes);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
dismiss();
break;
}
}
@Override
public void dismissCallBack(View view) {
Slog.v(TAG, "dismissCallBack");
}
};
closer.dialog = spacecleanDialog;
spacecleanDialog.getWindow().addFlags(
WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON|WindowManager.LayoutParams.FLAG_SECURE);
spacecleanDialog.show();
scdialog=spacecleanDialog;//此处是为了 当系统弹框未取消时,不再多次弹框,仅保持一次弹框
}
}
//使用时就非常简单
scheduledSpaceClean(fullspaceButtonText);