代码编织梦想

文章目录

  在台式电脑上,我们可以很轻松的最小化窗口,在后台做一些事情,并在任何时候都可以最大化窗口。但我们在android应用程序中看不到这一功能。如今,我们可以看到android提供了分屏功能,但这是操作系统提供的功能,而不是应用程序的单独功能。让我们制作一个应用程序,只需单击一个按钮即可将其最小化和最大化。该功能可以在很多方面帮助用户。假设你正在阅读一些带有数学计算的文档,那么最小化计算器将非常有用。


二、实现步骤

1.创建新项目

1.1要在Android Studio中创建新项目。请注意,先选择Emply Activity,再选择选择Java作为编程语言。

2.添加主题颜色

2.1为应用程序添加新颜色:

转到values->Colors.xml。可以在此处添加任何自定义颜色。我们添加了这两种颜色。

代码如下(示例):

<color name="gfgTheme">#FF2F8D46</color>
<color name="gfgThemeTwo">#FF098043</color>

2.2移除操作栏:

在Android Studio 4.1中,转到values->themes。有两个主题XML文件,一个用于亮模式,另一个用于暗模式。在这两个XML中,在样式块中将父属性更改为Theme.MaterialComponents.DayNight.NoActionBar。

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.FloatingWindow" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
    </style>
</resources>

2.3更改应用程序的主主题颜色:

更改应用程序的主要主题颜色:在同一文件中,第一个项目块必须与应用程序的主要颜色有关。在这里添加了新添加的颜色。在项目块中添加@color/gfgTheme 或 @color/gfgThemeTwo.

3.制作Layouts

3.1制作activity_main.xml文件

此 XML 文件制作应用程序的主要活动的布局。布局没有那么复杂。在约束布局中只有一个Button、TextView、EditText和ConstraintLayout中的一个又一个按钮。下面是 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"
    android:background="@android:color/white"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/buttonMinimize"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="Wink"
        android:textColor="@android:color/white"
        android:textSize="25sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/titleText"
        android:layout_width="match_parent"
        android:layout_height="70dp"
        android:gravity="center"
        android:text="浮动窗口"
        android:textColor="@color/gfgTheme"
        android:textSize="30sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonMinimize" />

    <EditText
        android:id="@+id/descEditText"
        android:layout_width="match_parent"
        android:layout_height="330dp"
        android:layout_marginTop="10dp"
        android:gravity="start"
        android:hint="这里写下内容"
        android:paddingLeft="20dp"
        android:paddingTop="10dp"
        android:paddingRight="20dp"
        android:paddingBottom="10dp"
        android:textColor="@android:color/black"
        android:textSize="22sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/titleText" />

    <Button
        android:id="@+id/saveBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:text="保存"
        android:textColor="@android:color/white"
        android:textSize="25sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/descEditText" />

</androidx.constraintlayout.widget.ConstraintLayout>

3.2制作floating_layout.xml文件

转到 res -> layout。右键单击layout -> New -> Layout Resource File。添加布局的名称(此处floating_layout)。此 XML 文件创建浮动窗口的布局。它具有与主布局相同的组件,但大小限制略有不同。下面是 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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <Button
        android:id="@+id/buttonMaximize"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"
        android:background="@color/gfgThemeTwo"
        android:text="Wink"
        android:textColor="@android:color/white"
        android:textSize="15sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/titleText"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="浮动窗口"
        android:textColor="@color/gfgThemeTwo"
        android:textSize="18sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/buttonMaximize" />

    <EditText
        android:id="@+id/descEditText"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        android:layout_marginBottom="10dp"
        android:gravity="start"
        android:hint="在这里写下"
        android:paddingLeft="20dp"
        android:paddingTop="10dp"
        android:paddingRight="20dp"
        android:paddingBottom="10dp"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@+id/saveBtn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/titleText" />

    <Button
        android:id="@+id/saveBtn"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginBottom="10dp"
        android:background="@color/gfgThemeTwo"
        android:text="保存"
        android:textColor="@android:color/white"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

4、制作Java程序

4.1为公共变量创建类:

首先,让我们先创建一个名为 Common 的包。右键单击项目包路径 -> new -> Package.

将弹出一个窗口。编写预期的包名称。将创建一个新包。

右键单击New Package -> 新建 -> Java 类。编写预期的类名。

创建两个公共字符串变量,一个是currentDesc,另一个是savedDesc。两者都使用空字符串启动。

下面是 Common.java 类的代码。

package com.example.floatingwindow.Common;

public class Common {
 
    public static String currentDesc = "";


    public static String savedDesc = "";
}

4.2更改MainActivity.java文件

首先,创建组件类的引用。将创建两个Buttons、一个AlertDialog和一个EditText 引用。

在到onCreate()之前,先创建了一些其他方法。

isMyServiceRunning():此方法有助于查找此应用程序的浮动窗口服务是否正在运行。当打开同一应用程序时,浮动窗口已经可见,因此需要此功能,然后需要停止浮动窗口服务。这是java代码:

   private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (FloatingWindowGFG.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

requestOverlayDisplayPermission():该方法有助于将应用程序重定向到设置以启用“在其他应用程序上显示”。虽然为此需要向AndroidManifest.xml文件添加额外的行。

为此,请转到app ->manifests-> AndroidManifest.xml。在application程序块之前添加此行:

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

java代码如下:

private void requestOverlayDisplayPermission() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setCancelable(true);
        builder.setTitle("Screen Overlay Permission Needed");
        builder.setMessage("Enable 'Display over other apps' from System Settings.");
        builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, RESULT_OK);
            }
        });
        dialog = builder.create();
        dialog.show();
    }

checkOverlayDisplayPermission():此方法实际上检查如果 API 级别超过 23,则是否在设置中启用了“在其他应用程序上显示”。下面是此函数的代码: 

 private boolean checkOverlayDisplayPermission() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }
}

现在这里是 MainActivity.java 文件的完整代码:

package com.example.floatingwindow;

import android.app.ActivityManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import com.example.floatingwindow.Common.Common;

public class MainActivity extends AppCompatActivity {

    private Button minimizeBtn;
    private AlertDialog dialog;
    private EditText descEditArea;
    private Button save;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        minimizeBtn = findViewById(R.id.buttonMinimize);
        descEditArea = findViewById(R.id.descEditText);
        save = findViewById(R.id.saveBtn);
        if (isMyServiceRunning()) {
            stopService(new Intent(MainActivity.this, FloatingWindowGFG.class));
        }
        descEditArea.setText(Common.currentDesc);
        descEditArea.setSelection(descEditArea.getText().toString().length());
        descEditArea.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                Common.currentDesc = descEditArea.getText().toString();
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });
        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Common.savedDesc = descEditArea.getText().toString();
                descEditArea.setCursorVisible(false);
                descEditArea.clearFocus();
                Toast.makeText(MainActivity.this, "Text Saved!!!", Toast.LENGTH_SHORT).show();
            }
        });

        minimizeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (checkOverlayDisplayPermission()) {
                    startService(new Intent(MainActivity.this, FloatingWindowGFG.class));
                    finish();
                } else {
                    requestOverlayDisplayPermission();
                }
            }
        });
    }

    private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
            if (FloatingWindowGFG.class.getName().equals(service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    private void requestOverlayDisplayPermission() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setCancelable(true);
        builder.setTitle("Screen Overlay Permission Needed");
        builder.setMessage("Enable 'Display over other apps' from System Settings.");
        builder.setPositiveButton("Open Settings", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, RESULT_OK);
            }
        });
        dialog = builder.create();
        dialog.show();
    }

    private boolean checkOverlayDisplayPermission() {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                return false;
            } else {
                return true;
            }
        } else {
            return true;
        }
    }
}

4.3:制作FloatingWindowGFG.java文件 

 创建另一个名为 FloatingWindowGFG 的类。转到项目包路径-> New -> Java 类

此类继承服务类。

现在,由于此类继承自 Service 类,因此此类可以用作清单文件中的服务。因此,在 AndroidManifest.xmlactivity之后和application结束之前添加此行。

<service android:name=".FloatingWindowGFG"
            tools:ignore="Instantiatable" />

FloatingWindowGFG.java代码:

package com.example.floatingwindow;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.Nullable;

import com.example.floatingwindow.Common.Common;

public class FloatingWindowGFG extends Service {
    private ViewGroup floatView;
    private int LAYOUT_TYPE;
    private WindowManager.LayoutParams floatWindowLayoutParam;
    private WindowManager windowManager;
    private Button maximizeBtn;
    private EditText descEditArea;
    private Button saveBtn;
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        DisplayMetrics metrics = getApplicationContext().getResources().getDisplayMetrics();
        int width = metrics.widthPixels;
        int height = metrics.heightPixels;
        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        LayoutInflater inflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
        floatView = (ViewGroup) inflater.inflate(R.layout.floating_layout, null);
        maximizeBtn = floatView.findViewById(R.id.buttonMaximize);
        descEditArea = floatView.findViewById(R.id.descEditText);
        saveBtn = floatView.findViewById(R.id.saveBtn);


        descEditArea.setText(Common.currentDesc);
        descEditArea.setSelection(descEditArea.getText().toString().length());
        descEditArea.setCursorVisible(false);


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

            LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {

            LAYOUT_TYPE = WindowManager.LayoutParams.TYPE_TOAST;
        }

        floatWindowLayoutParam = new WindowManager.LayoutParams(
                (int) (width * (0.55f)),
                (int) (height * (0.58f)),
                LAYOUT_TYPE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        floatWindowLayoutParam.gravity = Gravity.CENTER;

        floatWindowLayoutParam.x = 0;
        floatWindowLayoutParam.y = 0;

        windowManager.addView(floatView, floatWindowLayoutParam);

        maximizeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopSelf();
                windowManager.removeView(floatView);
                Intent backToHome = new Intent(FloatingWindowGFG.this, MainActivity.class);
                backToHome.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                startActivity(backToHome);
            }
        });
        descEditArea.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                Common.currentDesc = descEditArea.getText().toString();
            }

            @Override
            public void afterTextChanged(Editable editable) {
            }
        });
        floatView.setOnTouchListener(new View.OnTouchListener() {
            final WindowManager.LayoutParams floatWindowLayoutUpdateParam = floatWindowLayoutParam;
            double x;
            double y;
            double px;
            double py;

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = floatWindowLayoutUpdateParam.x;
                        y = floatWindowLayoutUpdateParam.y;
                        px = event.getRawX();
                        py = event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        floatWindowLayoutUpdateParam.x = (int) ((x + event.getRawX()) - px);
                        floatWindowLayoutUpdateParam.y = (int) ((y + event.getRawY()) - py);
                        windowManager.updateViewLayout(floatView, floatWindowLayoutUpdateParam);
                        break;
                }
                return false;
            }
        });
        descEditArea.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                descEditArea.setCursorVisible(true);
                WindowManager.LayoutParams floatWindowLayoutParamUpdateFlag = floatWindowLayoutParam;
                floatWindowLayoutParamUpdateFlag.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
                windowManager.updateViewLayout(floatView, floatWindowLayoutParamUpdateFlag);
                return false;
            }
        });


        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Common.savedDesc = descEditArea.getText().toString();
                descEditArea.setCursorVisible(false);
                WindowManager.LayoutParams floatWindowLayoutParamUpdateFlag = floatWindowLayoutParam;
                floatWindowLayoutParamUpdateFlag.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
                windowManager.updateViewLayout(floatView, floatWindowLayoutParamUpdateFlag);
                InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                inputMethodManager.hideSoftInputFromWindow(floatView.getApplicationWindowToken(), 0);
                Toast.makeText(FloatingWindowGFG.this, "Text Saved!!!", Toast.LENGTH_SHORT).show();
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        stopSelf();

        windowManager.removeView(floatView);
    }
}

三、总结

 1、运行结果展示

悬浮窗

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/AA670545946/article/details/127993032

android studio创建悬浮窗_小新110的博客-爱代码爱编程_androidstudio悬浮窗

第一步:创建一个项目。 第二步:创建一个service class,继承 Service public class MyService extends Service { private static final String TAG = "MyService"; //要引用的布局文件. ConstraintLayout to

android:实现安卓小程序-记事本(备忘录)的开发_头铁才学编程的博客-爱代码爱编程_android记事本项目

目录 1. 前言 2. 记事本功能需求 3. 部分关键代码解析及程序截图 3.1 记事本类的基本设计 3.2 记事本的数据存储设计 3.3 主界面的设计 3.4 记事本的编辑 3.5 记事本的背景色设置 3.6 记事本的闹铃功能 3.7 高级搜索 4. 总结 1. 前言 在学习安卓开发这门课程中期,学会了安卓开发的基本知识,比如

android应用activity、dialog、popwindow、toast窗口添加机制及源码分析_chuanao8829的博客-爱代码爱编程

1  背景 之所以写这一篇博客的原因是因为之前有写过一篇《Android应用setContentView与LayoutInflater加载解析机制源码分析》, 然后有人在文章下面评论和微博私信中问我关于Android应用Activity、Dialog、PopWindow加载显示机制是咋回事,所以我就写一 篇文章来分析分析吧(本文以Andro

使用Kotlin构建基本的Android CRUD应用-爱代码爱编程

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 Google最近为Kotlin授予了Android官方支持状态,但对于许多开发人员而言,它仍然很难理解。 最好的开始方法是自己创建一个完整的应用程序,这将在本教程中进行。

开始构建材质设计应用程序-爱代码爱编程

在我制作材料设计应用程序课程的视频中,您将学习如何创建材料设计应用程序的用户界面。 您将学习如何使用FAB(FloatingActionButtons),带有浮动标签的输入窗口小部件,操作栏菜单项等等。 本教程以本课程前面完成的基本设置工作为基础,但是您应该可以继续学习,并且始终可以在GitHub上检查源代码 。 如何创建Floati

人类高质量编程语言Delphi盛大发布2021新版本RAD Studio 11 Alexandria-爱代码爱编程

Embarcadero 很高兴地宣布 Delphi 11、C++Builder 11 和 RAD Studio 11 的发布。 RAD Studio 11 Alexandria 建立在 10.4 版本的功能集的基础上,并提供了许多新功能,包括使用高 DPI IDE 改进的用户体验.  在这篇博文中,我们想重点介绍 RAD 11 中的一些主要新功能和增

1000套安卓(Android)毕业设计(带论文)、大作业、实例快速下载 (Android Studio)-爱代码爱编程

ctrl+F 快速定位  序号类型项目名称1毕业设计毕业设计-基于安卓Android学生考勤信息管理系统.zip2毕业设计毕业设计-安卓Android教务选课成绩管理系统.zip3毕业设计114基于Android的理财记账本20141215+论文+需求文档+演示视频.zip.zip4毕业设计Android科大讯飞语音识别.zip5毕业设计基于a

android 上的浮动窗口:jetpack compose & room_yihanss的博客-爱代码爱编程

你有没有想过如何制作 Facebook Heads 和其他应用程序使用的那些浮动窗口?您是否曾经想在您的应用程序中使用相同的技术?这很容易,我将指导您完成整个过程。 在本文中,我将教您如何使用 Jetpack Compos

android floatingactionbutton(浮动动作按钮的动画 ) 使用详情_dt慕枫的博客-爱代码爱编程

目录 前言1. Floating Action Button2. 制作浮动操作按钮的菜单2.1 显示浮动操作按钮菜单2.2 隐藏浮动操作按钮菜单 3. 一个新的圆形动画3.1 创建一个Activity3.2 构建

android 13 wi-fi状态机流程及log分析_我想我思的博客-爱代码爱编程

本文基于Android 13源码解读,对Wi-Fi状态机调用流程进行梳理,并结合Log进行分析,便于大家理解Wi-Fi模块调用流程。 梳理出Wi-Fi状态机共有如下几种状态: mConnectableState mConnectingOrConnectedState mL2ConnectingState mL2ConnectedState mL

fiddler利用edxposed框架+trustmealready来突破ssl pinning抓取手机app数据_trustmealeady模块-爱代码爱编程

一、背景 在使用fiddler做代理抓取应用数据包时,如果要抓取到HTTPS数据,需要将fiddler证书导入到浏览器或手机。浏览器或手机设置好fiddler的代理地址,即可抓取到https数据包。 如果APP应用采用证书锁定后,将无法抓取到https数据,因为此时APP应用校验证书不通过,通常APP应用会断开网络连接,防止网络传输数据被抓取。 自从