更新时间:2025-09-11 GMT+08:00
分享

代码示例

串流页面:

public class HuaweiCloudActivity extends AppCompatActivity {
    private static final String TAG = "HuaweiCloudActivity";
    private  PlayerFragment mPlayerFragment;
    private LinearLayout float_opt;
    private CountDownTimer inactivityTimer;
    private static final long INACTIVITY_TIMEOUT = 3000; // 3秒
    private int failedNum;
    private Bundle extras;
    private LoadingLayout mLoadingLayout;
    private static Integer timer = 0;
    private  CloudPhoneCallBack callBack ;
    private Handler mHandler = new Handler();
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initView(savedInstanceState);
        ActivityManager.addActivity(this);
    }
    private void initView(Bundle savedInstanceState){
        View decorView = getWindow().getDecorView();
        Log.i(TAG, "======onCreate(Bundle savedInstanceState)");
        int uiOptions =
                View.SYSTEM_UI_FLAG_FULLSCREEN          // 隐藏状态栏
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION   // 隐藏导航栏
                        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; // 沉浸式模式(触摸后自动恢复)
        decorView.setSystemUiVisibility(uiOptions);
        // 监听变化,防止退出沉浸模式
        decorView.setOnSystemUiVisibilityChangeListener(visibility -> {
            if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                decorView.setSystemUiVisibility(uiOptions);
            }
        });
        setContentView(R.layout.activity_huawei_cloud);
        initPlayer(savedInstanceState);
    }
    @Override
    public boolean dispatchGenericMotionEvent(MotionEvent event) {
        // 手柄事件
        if (event.isFromSource(InputDevice.SOURCE_JOYSTICK) && event.getAction() == MotionEvent.ACTION_MOVE) {
            CloudPhoneClient.sendJoypadEvent(event);
            // 轴MotionEvent事件会额外触发对应的keyEvent
            return true;
        }
        return super.onGenericMotionEvent(event);
    }
    private static final Set<Integer> JOYSTICK_KEYCODE_SET = new HashSet<>(
            Arrays.asList(
                    // 方向键
                    KeyEvent.KEYCODE_DPAD_UP,
                    KeyEvent.KEYCODE_DPAD_DOWN,
                    KeyEvent.KEYCODE_DPAD_LEFT,
                    KeyEvent.KEYCODE_DPAD_RIGHT,
                    // ABXY
                    KeyEvent.KEYCODE_BUTTON_A,
                    KeyEvent.KEYCODE_BUTTON_B,
                    KeyEvent.KEYCODE_BUTTON_X,
                    KeyEvent.KEYCODE_BUTTON_Y,
                    // 左右肩键
                    KeyEvent.KEYCODE_BUTTON_L1,
                    KeyEvent.KEYCODE_BUTTON_L2,
                    KeyEvent.KEYCODE_BUTTON_R1,
                    KeyEvent.KEYCODE_BUTTON_R2,
                    // 左右摇杆按下
                    KeyEvent.KEYCODE_BUTTON_THUMBL,
                    KeyEvent.KEYCODE_BUTTON_THUMBR,
                    // 通用功能键
                    KeyEvent.KEYCODE_BUTTON_SELECT,
                    KeyEvent.KEYCODE_BUTTON_START
            ));
    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        // 转发手柄对应的按键
        int keyCode = event.getKeyCode();
        if (JOYSTICK_KEYCODE_SET.contains(keyCode)) {
            CloudPhoneClient.sendKeyEvent(keyCode, event.getAction());
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
    @Override
    protected void onResume() {
        Log.i(TAG, "======onResume()");
        super.onResume();
        // Activity恢复时重置计时器
    }
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        CloudPhoneClient.bindFragment(mPlayerFragment);
        CloudPhoneClient.switchStreamType(CloudPhoneConst.CLOUD_APP_SWITCH_STREAM_TYPE.BOTH);
    }
    @Override
    protected void onPause() {
        Log.i(TAG, "======onPause()");
        super.onPause();
        // Activity暂停时取消计时器
//        inactivityTimer.cancel();
    }
    @Override
    protected void onStop() {
        Log.i(TAG, "======onStop()");
        super.onStop();
    }
    @Override
    protected void onStart() {
        Log.i(TAG, "======onStart()");
        super.onStart();
    }
    private void initPlayer(Bundle savedInstanceState) {
        mPlayerFragment = (PlayerFragment) getFragmentManager().findFragmentById(R.id.fragment_player);
        callBack = CloudPhoneCallBack.getInstance();
        callBack.setProfileHandler(this::profileReceived);
        CloudPhoneClient.setPlayerCallback(callBack);
        CloudPhoneClient.setPlayerType(HMTP_PLAYER);
//        CloudPhoneClient.enableAudioKeeping(true);
        CloudPhoneClient.bindFragment(mPlayerFragment);
        CloudPhoneClient.switchStreamType(CloudPhoneConst.CLOUD_APP_SWITCH_STREAM_TYPE.BOTH);
//        CloudPhoneClient.switchStreamType(CloudPhoneConst.CLOUD_APP_SWITCH_STREAM_TYPE.BOTH);
        //执行串流的,串流结果成功会从onSuccsss返回通知,失败则是onFailure带code
//        CloudPhoneClient.start(mPlayerFragment, extras);
    }
    private void logBundleContents(Bundle bundle) {
        if (bundle == null) return;
        Log.i(TAG, "Bundle contains " + bundle.size() + " items:");
        for (String key : bundle.keySet()) {
            Log.i(TAG, key + " = " + bundle.get(key));
        }
    }
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "======onSaveInstanceState()");
        NetworkInfoComp.netWorkMap.remove("帧率");
        NetworkInfoComp.netWorkMap.remove("下行流量");
        NetworkInfoComp.netWorkMap.remove("延迟");
        super.onSaveInstanceState(outState);
        outState.putBundle("EXTRA_BUNDLE", getIntent().getExtras());
    }
    @Override
    protected void onDestroy() {
        Log.i(TAG, "======onDestroy()");
        super.onDestroy();
        CloudPhoneClient.setUnPlayerCallback(callBack);
        mHandler.removeCallbacksAndMessages(null);
        ActivityManager.removeActivity(this);
    }
    private boolean isFmActive() {
        final AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        if (am == null) {
            Log.w(TAG, "isFmActive: couldn't get AudioManager reference");
            return false;
        }
        return am.isMusicActive();
    }
    /**
     * 再次连接
     */
    private void linkAgain() {
        //执行串流的,串流结果成功会从onSuccsss返回通知,失败则是onFailure带code
        CloudPhoneClient.stop();
        CloudPhoneClient.start(mPlayerFragment, extras);
        onResume();
    }
    public void profileReceived(String s) {
        NetInfo netInfo = JSONUtil.fromJson(s, NetInfo.class);
        int rrt = Integer.parseInt(netInfo.getRtt().replaceAll("[^0-9]", ""));
        if(rrt>100){
//            CloudPhoneClient.setProfile(1);
            timer = 3;
        } else if (rrt<80) {
            timer = Math.max(0, timer - 1);
            if(timer==0){
//                CloudPhoneClient.setProfile(0);
            }
        }
        if(AppApplication.getInstance().getDebugMode()) {
            String numberStr = netInfo.getBr().replaceAll("[^0-9.]", "");
            String letters = netInfo.getBr().replaceAll("[^a-zA-Z]", "").toUpperCase();
            double v = Double.parseDouble(numberStr) / 8;
            DecimalFormat df = new DecimalFormat("#0.00");
            String formattedResult = df.format(v);
            List<NetworkConfig> networkConfigList = AppApplication.getInstance().getDebugConfig();
            if(networkConfigList.stream().anyMatch(item->item.getLabel().equals("发送帧"))){
                NetworkInfoComp.netWorkMap.put("发送帧", netInfo.getFps());
            }
            if(networkConfigList.stream().anyMatch(item->item.getLabel().equals("下行流量"))){
                NetworkInfoComp.netWorkMap.put("下行流量",formattedResult+letters);
            }
            if(networkConfigList.stream().anyMatch(item->item.getLabel().equals("网络延迟"))){
                NetworkInfoComp.netWorkMap.put("网络延迟", netInfo.getRtt());
            }
            NetworkInfoComp.reloadGirdView();
        }
        Log.i(TAG, "======onProfileReceived(String s).s="+s);
    }
}

回调处理对象:

package com.KooCabin.service;
import android.app.Activity;
import android.util.Log;
import androidx.core.util.Consumer;
import com.KooCabin.activity.HuaweiCloudActivity;
import com.KooCabin.base.BasePresenter;
import com.KooCabin.ui.playerfloat.FloatWindowMainView;
import com.cloudphone.client.api.CloudPhoneClient;
import com.cloudphone.client.api.CloudPhoneConst;
import com.cloudphone.client.bean.AppInfo;
import com.cloudphone.client.bean.AppLifeCycle;
import com.cloudphone.client.bean.AppOperateResponse;
import com.cloudphone.client.bean.DiskUsageInfo;
import com.cloudphone.client.bean.GetAppsRsp;
import com.huawei.kp.KPClientStat;
import com.huawei.kp.KPCloudStat;
import lombok.Setter;
@Setter
public class CloudPhoneCallBack implements CloudPhoneClient.Callback, CloudPhoneClient.Callback.AppCallback {
    private static volatile CloudPhoneCallBack instance;
    // 私有构造方法
    private CloudPhoneCallBack() {
        // 防止外部实例化
    }
    // 公共静态获取实例方法
    public static CloudPhoneCallBack getInstance() {
        if (instance == null) {
            synchronized (CloudPhoneCallBack.class) {
                if (instance == null) {
                    instance = new CloudPhoneCallBack();
                }
            }
        }
        return instance;
    }
    private static final String TAG = "CloudPhoneCallback";
    private Consumer<AppOperateResponse<GetAppsRsp>> appHandler;
    private Consumer<Void> startHandler;
    private Consumer<AppOperateResponse<String>> unInstallHandler;
    private Consumer<AppOperateResponse<String>> unLoadAppHandler;
    private Consumer<AppOperateResponse<String>> startAppHandler;
    private Consumer<AppOperateResponse<String>> closeAppHandler;
    private Consumer<String> profileHandler;
    private Consumer<Void> streamSuccessHandler;
    private Consumer<AppOperateResponse<DiskUsageInfo>> usageHandler;
    @Override
    public void onGetInstalledApps(AppOperateResponse<GetAppsRsp> appOperateResponse) {
        if(appHandler != null) {
            appHandler.accept(appOperateResponse);
        }
        Log.i(TAG, "onGetInstalledApps success");
    }
    @Override
    public void onSuccess() {
        if(streamSuccessHandler!=null){
            streamSuccessHandler.accept(null);
        }
    }
    @Override
    public void onTerminated() {
    }
    @Override
    public void onFailure(int i, String s) {
    }
    @Override
    public void onMenuOnClick(Activity activity, int i) {
    }
    @Override
    public String getUrl() {
        return "";
    }
    @Override
    public void lifecycle(Activity activity, int i) {
    }
    @Override
    public void onOrientationChange(int i) {
    }
    @Override
    public void onSlotsInfo(String s) {
    }
    @Override
    public void onRoomInfoUpdate(String s) {
    }
    @Override
    public void onPermissionRequest(String s) {
    }
    @Override
    public void onPermissionResult(String s) {
    }
    @Override
    public void onProfileReceived(String s) {
        if(profileHandler!=null){
            profileHandler.accept(s);
        }
    }
    @Override
    public void onProfileChanged(int i, boolean b) {
    }
    @Override
    public void onExitConfirm(int i) {
    }
    @Override
    public void onUserExit() {
    }
    @Override
    public void onExtMessageReceived(Activity activity, String s) {
    }
    @Override
    public void onScreenshotUpdate(String s, String s1) {
    }
    @Override
    public void onScreenshotAuthFailed(String s) {
    }
    @Override
    public void onKicked(String s) {
    }
    @Override
    public void onPermissionGranted(String[] strings) {
    }
    @Override
    public void onPermissionDenied(String[] strings) {
    }
    @Override
    public void onHttpResponse(String s) {
    }
    @Override
    public void onActionMessage(String s) {
    }
    @Override
    public void onPerfLog(int i, String s) {
    }
    @Override
    public void onSensorInjectEvent(String s) {
    }
    @Override
    public void onCloudStatistics(KPCloudStat kpCloudStat) {
    }
    @Override
    public void onClientStatistics(KPClientStat kpClientStat) {
    }
    @Override
    public void onStreamStarted() {
        Log.i("11111", "onStreamStarted======onSuccess()");
//        CloudPhoneClient.switchStreamType(CloudPhoneConst.CLOUD_APP_SWITCH_STREAM_TYPE.BOTH);
        if(startHandler!=null){
            startHandler.accept(null);
        }
    }
    @Override
    public void onCloseApp(AppOperateResponse<String> appOperateResponse) {
        Log.i("11111", "======onCloseApp()");
        if(closeAppHandler!=null){
            closeAppHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onStartApp(AppOperateResponse<String> appOperateResponse) {
        Log.i("CALLBACK:","=====onStartApp=======");
        if(startAppHandler!=null){
            startAppHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onGetRunningApps(AppOperateResponse<GetAppsRsp> appOperateResponse) {
        if(appHandler!=null){
            appHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onRestartApp(AppOperateResponse<String> appOperateResponse) {
        Log.i("11111", "======onRestartApp()");
    }
    @Override
    public void onUninstallApp(AppOperateResponse<String> appOperateResponse) {
        if(unInstallHandler!=null){
            unInstallHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onLoadApp(AppOperateResponse<String> appOperateResponse) {
        if(unLoadAppHandler!=null){
            unLoadAppHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onGetDiskUsage(AppOperateResponse<DiskUsageInfo> appOperateResponse) {
        if(usageHandler!=null){
            usageHandler.accept(appOperateResponse);
        }
    }
    @Override
    public void onAPKInstallState(AppOperateResponse<AppInfo> appOperateResponse) {
        Log.i("11111", "======onAPKInstallState()");
    }
    @Override
    public void onAppLifeCycle(AppOperateResponse<AppLifeCycle> appOperateResponse) {
        Log.i("11111", "======onAppLifeCycles()");
    }
}

串流页面布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/player_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/fragment_player"
        android:name="com.nbc.acsdk.widget.PlayerFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!--串流页面其他自定义UI自行添加-->
    <!--    悬浮操作-->
    <com.KooCabin.ui.NetworkInfoComp
        android:id="@+id/network_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top|end"
         />
</FrameLayout>

相关文档