Android 副屏调用

Android原生副屏功能API,不需要集成SDK。文末附源码

具体调用流程如下

-副屏申请权限

Androidmanifest.xml中增加如下代码:

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

== 简单功能示例 ==

效果图:

主屏:

 副屏初始页面:

 副屏接收到主屏信息页面:

代码如下:

1.定义双屏Service,并在manifest文件中声明

public class DualScreenService extends Service {

    public static final String SUB_ACTIVITY_TEST_UPDATE_CONTENT = "sub_activity_test_update_content";
    // 获取设备上的屏幕
    DisplayManager mDisplayManager;// 屏幕管理器
    Display[] displays;// 屏幕数组
    SubPresentation subPresentation; // (继承Presentation)

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // 双屏异显
        mDisplayManager = (DisplayManager) this.getSystemService(Context.DISPLAY_SERVICE);
        displays = mDisplayManager.getDisplays();
        registerRecevicer();
    }

    private void registerRecevicer() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(SUB_ACTIVITY_TEST_UPDATE_CONTENT);
        registerReceiver(receiver, filter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        showView();
        return super.onStartCommand(intent, flags, startId);
    }

    @SuppressLint("NewApi")
    private void showView() {
        if (displays.length < 2) {
            Toast.makeText(getApplicationContext(), "开启副屏失败", Toast.LENGTH_SHORT).show();
            return;
        }
        subPresentation = new SubPresentation(getApplicationContext(), displays[1]);// displays[1]是副屏
        subPresentation.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        subPresentation.setCancelable(false);
        subPresentation.show();
    }

    BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case SUB_ACTIVITY_TEST_UPDATE_CONTENT:
                    subPresentation.updateContent(intent.getStringExtra("content"));
                    break;
                default:
                    break;
            }
        }
    };
}

<service
    android:name=".DualScreenService"
    android:exported="false" />

2.自定义副屏演示类

public class SubPresentation extends Presentation {

    private ActivitySubScreenBinding binding;

    public SubPresentation(Context mContext, Display display) {
        super(mContext, display);
        binding = ActivitySubScreenBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    public void updateContent(String content) {
        binding.tvContent.setText("接收到:"+content);
    }

}

说明:以上两个类是副屏功能最基础的两个类,service中主要是声明副屏服务的创建,创建并接收系统广播,处理主副屏之间的信息传递。SubPresentation 可以理解成副屏页面,有点Activity的概念,在其中主要是处理副屏UI上面的变化。

按照示例图,我们只做了主屏上点击按钮,发送”你好“到副屏,并显示出来。

那么我们声明了一个SUB_ACTIVITY_TEST_UPDATE_CONTENT指令名称,也就是只要广播中发现了这条指令,就调用subPresentation的updateContent方法,进而更改binding.tvContent的文本属性

MainActivity代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkDualScreenPermission();
        Button btn_send = findViewById(R.id.btn_send);
        btn_send.setOnClickListener(view -> {
            Intent intent = new Intent();
            intent.setAction(DualScreenService.SUB_ACTIVITY_TEST_UPDATE_CONTENT);
            intent.putExtra("content", "你好!");
            sendBroadcast(intent);
        });
    }

    public void checkDualScreenPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            if (!Settings.canDrawOverlays(MainActivity.this)) {
                new CommonDialog.Builder(this).setTitle("提示")
                        .setContent("副屏功能需要开启相关权限")
                        .setEnsureStr("前往设置")
                        .setCancelStr("退出应用")
                        .setEnsureClick(v1 -> {
                            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                    Uri.parse("package:" + getPackageName()));
                            startActivityForResult(intent, 10);
                        })
                        .setCancelClick(v -> {
                            finish();
                        })
                        .show();
            } else {
                Intent service = new Intent();
                service.setPackage(this.getPackageName());// 这里你需要设置你应用的包名
                service.setClass(this, DualScreenService.class);
                this.startService(service);
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 10) {
            if (Build.VERSION.SDK_INT >= 23) {
                if (!Settings.canDrawOverlays(this)) {
                    // SYSTEM_ALERT_WINDOW permission not granted...
                    new CommonDialog.Builder(this).setTitle("提示")
                            .setContent("权限被拒绝或未开启")
                            .setEnsureStr("前往设置")
                            .setCancelStr("退出应用")
                            .setEnsureClick(v1 -> {
                                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                        Uri.parse("package:" + getPackageName()));
                                startActivityForResult(intent, 10);
                            })
                            .setCancelClick(v -> {
                                finish();
                            })
                            .show();
                } else {
                    Intent service = new Intent();
                    service.setPackage(this.getPackageName());// 这里你需要设置你应用的包名
                    service.setClass(this, DualScreenService.class);
                    this.startService(service);
                }
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Intent service = new Intent();
        service.setPackage(getPackageName());// 这里你需要设置你应用的包名
        service.setClass(MainActivity.this, DualScreenService.class);
        stopService(service);
    }
}

说明:

1.Android调用副屏,需要设置权限,图示如下

 

这里跳转设置页开启权限需要与用户交互,并且处理用户点击了”前往设置”按钮,但是没有开启开关又返回的情况,进行拦截,避免发生后续的崩溃或者是副屏显示异常的情况。

代码中checkDualScreenPermission()和onActivityResult()处理了该逻辑

2.具体的调用副屏的代码

Intent intent = new Intent();
intent.setAction(DualScreenService.SUB_ACTIVITY_TEST_UPDATE_CONTENT);
intent.putExtra("content", "你好!");
sendBroadcast(intent);

3.为了避免资源浪费,当app退出时,需要注销service

@Override
protected void onDestroy() {
    super.onDestroy();
    Intent service = new Intent();
    service.setPackage(getPackageName());// 这里你需要设置你应用的包名
    service.setClass(MainActivity.this, DualScreenService.class);
    stopService(service);
}

写在后面,除了String文本,还可以通过intent传递所有支持的数据类型或者是序列化的对象数据,以实现业务中需要的各种UI场景。这里只是做了最简单的展示,如果需要实际代码,可以参考餐饮零售会员的实际业务代码。

demo源码

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Android 9 中实现输入法显示,可以通过以下步骤: 1. 在 AndroidManifest.xml 文件中声明一个具有 android.permission.WRITE_SECURE_SETTINGS 权限的服务。 ```xml <manifest> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> <application> <service android:name=".YourServiceName" android:permission="android.permission.BIND_INPUT_METHOD"> <meta-data android:name="android.view.im" android:resource="@xml/method" /> <meta-data android:name="android.permission" android:value="android.permission.WRITE_SECURE_SETTINGS" /> <intent-filter> <action android:name="android.view.InputMethod" /> </intent-filter> </service> </application> </manifest> ``` 2. 创建一个自定义的输入法服务 YourServiceName,并在 onCreate() 方法中调用 setSecureSetting() 方法设置 secure_setting_show_ime_with_hard_keyboard 值为 1。 ```java public class YourServiceName extends InputMethodService { @Override public void onCreate() { super.onCreate(); // 设置 secure_setting_show_ime_with_hard_keyboard 值为 1 setSecureSetting(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, "1"); } private void setSecureSetting(String key, String value) { try { ContentResolver resolver = getContentResolver(); Settings.Secure.putString(resolver, key, value); } catch (Exception e) { Log.e(TAG, "Failed to set secure setting", e); } } } ``` 3. 在 res/xml 目录下创建 method.xml 文件,并指定输入法对应的键盘布局。 ```xml <input-method xmlns:android="http://schemas.android.com/apk/res/android" android:settingsActivity="YourSettingsActivityName" android:canRequestEnhancedWebAccessibility="true" android:canRequestFilterKeyEvents="true" android:inputMethod="YourInputMethodName" android:label="YourLabelName"> <subtype android:label="YourSubtypeName" android:imeSubtypeLocale="YourSubtypeLocale" android:imeSubtypeMode="YourSubtypeMode" android:imeSubtypeExtraValue="YourSubtypeExtraValue" android:isAsciiCapable="true" /> </input-method> ``` 4. 在 AndroidManifest.xml 文件中声明一个 SettingsActivity,并在 onCreate() 方法中调用 setResult() 方法以返回结果。 ```xml <activity android:name=".YourSettingsActivityName" android:exported="true" android:label="YourSettingsActivityLabel"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> ``` ```java public class YourSettingsActivityName extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setResult(Activity.RESULT_OK); finish(); } } ``` 通过以上步骤,即可在 Android 9 中实现输入法显示。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时间如潮水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值