Android在悬浮窗快捷中心中实现设置系统亮度功能

需求

在悬浮窗的快捷中心中实现设置屏幕亮度的功能,一共有25/50/75/100%以及Auto五中模式。

实现方案

这个功能刚开始查资料的时候觉得挺简单,就几句代码的事情,如下:

/**
 * 设置屏幕亮度
 * @param brightness 即我们所希望的25/50/75/100
 */
private void setScreenBrightness(int brightness) {
	// TODO Auto-generated method stub
	Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, (brightness * 255 / 100));
}

并且可以通过下面的代码直接写入屏幕亮度模式(自动/普通)

Settings.System.putInt(mContext.getContentResolver(), 
		Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); //普通模式
Settings.System.putInt(mContext.getContentResolver(), 
		Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); //自动模式

遇到问题

由于我用的测试设备是Nexus 5和MotoX,在Android Lollipop和KatKit版本上没有问题,点击Button后都生效,但是项目的测试童靴在别的测试机型和系统上发现了不能立即生效的问题,要在设置里点一次亮度进度条才生效。

更好的方案

没办法又遇到碎片化的问题,我很快定位到肯定是我的setScreenBrightness方法没有生效,在网上找了下资料,发现了不是这条语句不行,而是这套代码不够严谨,有另一套更准确的实现方案,参考代码。里面用到了这个方法:

/** 
 * 设置屏幕亮度,这会反映到真实屏幕上 
 *  
 * @param activity 
 * @param brightness 
 */  
public void setActScreenBrightness(final Activity activity, final int brightness) {  
    final WindowManager.LayoutParams lp = activity.getWindow().getAttributes();  
    lp.screenBrightness = brightness / (float) MAX_BRIGHTNESS;  
    activity.getWindow().setAttributes(lp);  
}  

其中的getWindow().getAttributes()和getWindow().setAttributes(lp)都必须通过activity调用,但是我们的控制悬浮窗是一个View,里面调不到这两个方法,而悬浮窗的创建是通过Service后台控制是没有Activity进入的,怎么办?

优化方案

那么我们就造一个Activity出来,可是这样不会影响到显示界面吗?如果只是普通的Activity是肯定会的,别的不说,至少有一个打开的动画并且又在悬浮窗上覆盖了一层View。这个时候我们就要对这个Activity做特殊处理了,由于我们只是要借助Activity的接口实现我们的方法而已,其他的功能(包括界面)我们都可以不要,所以这里应该是建造一个虚拟(Dummy)的Activity,什么事虚拟的,就是透明的无动画的成功后自动消失的,以便让用户察觉不到。

具体方案

先来看看这个DummyBrightnessActivity的代码,具体的功能在代码后有注释,创建后立即设置立即消失

/**
 * @Function 虚拟的亮度窗口,用于调用设置亮度接口
 * @date 2014-12-2 
 * 
 * @author rivers
 * @version 1.0
 */
public class DummyBrightnessActivity extends BaseActivity {
	
    private static final int DELAYED_MESSAGE = 1;

    private Handler handler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);            
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if(msg.what == DELAYED_MESSAGE) {
                    DummyBrightnessActivity.this.finish(); //关闭该Activity
                }
                super.handleMessage(msg);
            }
        };
        Intent brightnessIntent = this.getIntent();
        int brightness = brightnessIntent.getIntExtra("brightness value", 0); //获取需要改变的亮度值
        Settings.System.putInt(this.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, brightness);
        WindowManager.LayoutParams lp = getWindow().getAttributes(); //调用我们需要立即实现的接口
        lp.screenBrightness = brightness / 255.0f; //计算
        getWindow().setAttributes(lp); //调用我们需要立即实现的接口

        Message message = handler.obtainMessage(DELAYED_MESSAGE);
        handler.sendMessageDelayed(message,0);  //立即发送message关闭该窗口
    }
}
然后要在AndroidManifest.xml中声明该Activity

<activity android:name="yourPackageName.DummyBrightnessActivity"
    android:taskAffinity="yourPackageName.Dummy"
    android:excludeFromRecents="true"
    android:theme="@style/EmptyActivity">          
</activity>
上面已经实现了创建设置后自动消失的功能了,那么还剩下透明和无动画要做到,就在这个android:theme="@style/EmptyActivity"风格中

<style name="EmptyActivity" parent="android:Theme.Dialog">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowAnimationStyle">@android:style/Animation.Toast</item>
    <item name="android:background">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:colorForeground">@android:color/transparent</item>
</style>

这样一来我们所需要的这个虚拟Activity就算是已经创建好了,只需要在快捷中心的View中调用下面的跳转代码,这个功能就算是完成了

private void intentToDummyBrightness(int brightness) {
    Intent intent = new Intent(mContext, DummyBrightnessActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //注意一定要使用New Task
    intent.putExtra("brightness value", brightness); 
    mContext.startActivity(intent);
}

总结

开发这个功能的时候,我犯了想当然以及重视程度不足的问题,觉得只不过调用一个读取/写入的功能就能实现了,实不知那不是最精确的办法,并且还有碎片化的问题没测试就提交了版本,下次考虑问题该更全面。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 在 AndroidManifest.xml 文件添加权限: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. 创建一个服务类,继承自 Service: ```java public class FloatingService extends Service { @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { createFloatingWindow(); return super.onStartCommand(intent, flags, startId); } private void createFloatingWindow() { // 创建悬浮窗 } @Override public void onDestroy() { super.onDestroy(); // 关闭悬浮窗 } } ``` 3. 在 onCreate() 方法启动服务: ```java public void onCreate() { super.onCreate(); Intent intent = new Intent(this, FloatingService.class); startService(intent); } ``` 4. 在 createFloatingWindow() 方法创建悬浮窗: ```java private void createFloatingWindow() { // 初始 WindowManager WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); // 创建悬浮窗布局 View floatingView = LayoutInflater.from(this).inflate(R.layout.floating_window, null); // 设置悬浮窗布局参数 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; layoutParams.format = PixelFormat.TRANSLUCENT; layoutParams.gravity = Gravity.CENTER; // 添加悬浮窗布局到 WindowManager windowManager.addView(floatingView, layoutParams); } ``` 5. 在 onDestroy() 方法关闭悬浮窗: ```java @Override public void onDestroy() { super.onDestroy(); WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); windowManager.removeView(floatingView); } ``` 6. 创建悬浮窗布局文件 floating_window.xml: ```xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:background="#FF0000" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:text="悬浮窗" android:textColor="#FFFFFF" android:textSize="20sp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> ``` 7. 运行程序即可看到悬浮窗

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值