logcat:2025-06-23 15:10:40.037 1491-3220 ActivityTrigger system_server E activityStartTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11
2025-06-23 15:10:40.038 1491-3220 ActivityTrigger system_server E activityResumeTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11
2025-06-23 15:10:40.044 1491-3220 ActivityTrigger system_server E activityResumeTrigger: not whiteListedcom.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity/11
---------------------------- PROCESS STARTED (15498) for package com.hik.netsdk.SimpleDemo ----------------------------
2025-06-23 15:10:40.330 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.366 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.399 15498-15498 NetworkSecurityConfig com.hik.netsdk.SimpleDemo D No Network Security Config specified, using platform default
2025-06-23 15:10:40.406 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.412 15498-15498 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.446 15498-15533 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.450 15498-15498 AccessibilityManager com.hik.netsdk.SimpleDemo D AccessibilityManager status: mPackageName = com.hik.netsdk.SimpleDemo, mOptimizeEnabled = true, mIsEnabled = false, mIsUiAutomationEnabled = false, mIsInterestedPackage =false
2025-06-23 15:10:40.461 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D initViewContentFetcherClass
2025-06-23 15:10:40.461 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D getInterceptorPackageInfo
2025-06-23 15:10:40.462 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D getInitialApplication took 1ms
2025-06-23 15:10:40.462 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D packageInfo.packageName: com.miui.catcherpatch
2025-06-23 15:10:40.464 15498-15533 ResourceType com.hik.netsdk.SimpleDemo W No package identifier when getting name for resource number 0x00000000
2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Do partial code cache collection, code=30KB, data=19KB
2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I After code cache collection, code=30KB, data=19KB
2025-06-23 15:10:40.471 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Increasing code cache capacity to 128KB
2025-06-23 15:10:40.477 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D initViewContentFetcherClass took 16ms
2025-06-23 15:10:40.477 15498-15533 ContentCatcher com.hik.netsdk.SimpleDemo I ViewContentFetcher : ViewContentFetcher
2025-06-23 15:10:40.478 15498-15533 ViewContentFactory com.hik.netsdk.SimpleDemo D createInterceptor took 16ms
2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Do partial code cache collection, code=39KB, data=37KB
2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I After code cache collection, code=39KB, data=37KB
2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Increasing code cache capacity to 256KB
2025-06-23 15:10:40.670 15498-15503 zygote64 com.hik.netsdk.SimpleDemo I Compiler allocated 4MB to compile void android.view.View.<init>(android.content.Context, android.util.AttributeSet, int, int)
2025-06-23 15:10:40.772 15498-15498 AndroidRuntime com.hik.netsdk.SimpleDemo D Shutting down VM
2025-06-23 15:10:40.774 15498-15498 AndroidRuntime com.hik.netsdk.SimpleDemo E FATAL EXCEPTION: main
Process: com.hik.netsdk.SimpleDemo, PID: 15498
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hik.netsdk.SimpleDemo/com.hik.netsdk.SimpleDemo.View.MainActivity}: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatTextView cannot be cast to androidx.appcompat.widget.Toolbar
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
Caused by: java.lang.ClassCastException: androidx.appcompat.widget.AppCompatTextView cannot be cast to androidx.appcompat.widget.Toolbar
at com.hik.netsdk.SimpleDemo.View.MainActivity.initUIComponents(MainActivity.java:137)
at com.hik.netsdk.SimpleDemo.View.MainActivity.onCreate(MainActivity.java:117)
at android.app.Activity.performCreate(Activity.java:7040)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2809)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2931)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1620)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:173)
at android.app.ActivityThread.main(ActivityThread.java:6698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:782)
2025-06-23 15:10:40.804 15498-15498 Process com.hik.netsdk.SimpleDemo I Sending signal. PID: 15498 SIG: 9 依据上述logcat日志解决在VideoListActivity中实现通过用户在设备列表选择Videolist播放通道后传递参数跨应用ysy1.apk中实现已经云接入萤石开放平台的75台摄像头实现实时预览(即摄像头实时监控,现在只需要实现最基础的实时预览)的功能 VideoListActivity:package com.jd.projects.wlw.video;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.FileProvider;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.jd.projects.wlw.DeviceMapActivity;
import com.jd.projects.wlw.R;
import com.jd.projects.wlw.adapter.VideoDevAdapter;
import com.jd.projects.wlw.dialog.CreateLoadingDialog;
import com.jd.projects.wlw.hkdemo.HkMainActivity;
import com.jd.projects.wlw.units.FileUtils;
import com.jd.projects.wlw.units.NetHelper;
import com.jd.projects.wlw.xmvideo.DahuaVideoActicity;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class VideoListActivity extends Activity {
private ArrayList<Map<String, String>> mvideolist;
private Context context;
public static Map<String, String> map;
public Button curve3;
private String aliasname = "";//站点别名
public static final String package_name = "com.hik.netsdk.SimpleDemo";
public static final String package_name2 = "com.example.funsdkdemo";
public static final String APK_NAME = "ysy1.apk";
public static final String APK_NAME2 = "zxcv.apk";
private int curersioncode = 11;//萤石云插件apk最新版本号。
private int curersioncode2 = 5;//雄迈插件apk最新版本号。
//private String Appkey = "05381ff665c843c398a0a3b6d6e341ac";
private String Appkey = "";
private String devserial = "";
private String VerifyCode = "";
private int channelName = 1;
private String accessToken = "";
Map<String, String> mmap;
private String response = "";
private CreateLoadingDialog loadingDialg = new CreateLoadingDialog();
private String user_control_power, site_control_power;
private String netmode = "";
private String xmip = "";
private String xmport = "";
private String xmusername = "";
private String xmpassword = "";
private String devSn = "";
private String xmmark = "";
private double intentLat = 0.0;
private double intentLng = 0.0;
@SuppressLint("HandlerLeak")
Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
loadingDialg.dismissLoadingDialog();
System.out.println("--访问令牌接口返回--" + response);
try {
JSONObject object = new JSONObject(response);
String code = object.get("code").toString();
String mmsg = object.get("msg").toString();
if (code.equals("200")) {
JSONObject object2 = (JSONObject) object.get("data");
accessToken = object2.get("accessToken").toString();
System.out.println("--访问令牌为:--" + accessToken);
openAPK();
} else {
Toast.makeText(context, mmsg, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// TODO: handle exception
}
break;
default:
break;
}
}
;
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.avtivity_videolist);
intentLat = getIntent().getDoubleExtra("intentLat", 0.0);
intentLng = getIntent().getDoubleExtra("intentLng", 0.0);
context = this;
initData();
initView();
}
private void initView() {
ListView listView = (ListView) findViewById(R.id.Videolist);
curve3 = (Button) findViewById(R.id.curve3);
VideoDevAdapter adapter = new VideoDevAdapter(mvideolist, context);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
map = mvideolist.get(position);
String mark = map.get("mark");
if (mark.equals("yiwei")) {
SerializableMap myMap = new SerializableMap();
myMap.setMap(map);
Bundle bundle = new Bundle();
bundle.putSerializable("map", myMap);
bundle.putString("user_control_power", user_control_power);
bundle.putString("site_control_power", site_control_power);
bundle.putString("netmode", netmode);
Intent intent = new Intent();
intent.putExtras(bundle);
intent.setClass(getApplicationContext(), YwVideoPlayerActivity.class);
startActivity(intent);
} else if (mark.equals("haikang")) {
// 跳转海康页面
String strIP = map.get("serverUrl").trim();
String nPort = map.get("serverPort").trim();
String strUser = map.get("userName").trim();
String strPsd = map.get("userPwd").trim();
Bundle bundle = new Bundle();
bundle.putString("ip", strIP);
bundle.putString("port", nPort);
bundle.putString("username", strUser);
bundle.putString("password", strPsd);
bundle.putString("user_control_power", user_control_power);
bundle.putString("site_control_power", site_control_power);
bundle.putString("netmode", netmode);
Intent intent2 = new Intent();
intent2.putExtras(bundle);
intent2.setClass(getApplicationContext(), HkMainActivity.class);
startActivity(intent2);
} else if (mark.equals("dahua")) {
// 跳转大华页面
String strIP = map.get("serverUrl").trim();
String nPort = map.get("serverPort").trim();
String strUser = map.get("userName").trim();
String strPsd = map.get("userPwd").trim();
Bundle bundle = new Bundle();
bundle.putString("ip", strIP);
bundle.putString("port", nPort);
bundle.putString("username", strUser);
bundle.putString("password", strPsd);
bundle.putString("user_control_power", user_control_power);
bundle.putString("site_control_power", site_control_power);
bundle.putString("netmode", netmode);
Intent intent2 = new Intent();
intent2.putExtras(bundle);
intent2.setClass(getApplicationContext(), DahuaVideoActicity.class);
startActivity(intent2);
} else if (mark.equals("xiongmai") || mark.equals("4Gxiongmai")) {
xmip = map.get("serverUrl").trim();
xmport = map.get("serverPort").trim();
xmusername = map.get("userName").trim();
xmpassword = map.get("userPwd").trim();
devSn = map.get("devSn").trim();//雄迈4G球机序列号
xmmark = mark;
openAPK2();
} else if (mark.equals("HK4GIPC01")) {
// 海康4G摄像机---公司现在暂无使用
String strIP = map.get("serverUrl");//设备序列号
String strUser = map.get("userName");//设备验证名
String strPsd = map.get("userPwd");
Bundle bundle = new Bundle();
bundle.putString("ip", strIP.trim());
bundle.putString("username", strUser.trim());
bundle.putString("password", strPsd.trim());
Intent intent2 = new Intent();
intent2.putExtras(bundle);
intent2.setClass(getApplicationContext(), Hk4GVideoMain.class);
startActivity(intent2);
} else if (mark.equals("HK4GIPC02")) {
// 萤石云平台摄像机
devserial = map.get("serverUrl").trim();// 设备序列号
VerifyCode = map.get("serverPort").trim();// 设备验证码
Appkey = map.get("userName").trim();// AppKey
channelName = Integer.parseInt(map.get("channelNum").trim());// channelName
String secret = map.get("userPwd").trim();// Secret
//System.out.println("---测试参数--"+appkey+"---"+secret);
if (accessToken.equals("")) {
loadingDialg.createLoadingDialog(context, "访问令牌获取中...").show();
// 获取访问令牌
mmap = new HashMap<>();
mmap.put("appKey", Appkey);
mmap.put("appSecret", secret);
new Thread(new Runnable() {
@Override
public void run() {
response = NetHelper.submitPostData("https://open.ys7.com/api/lapp/token/get", mmap,
"utf-8");//encode
mHandler.sendEmptyMessage(0);
}
}).start();
} else {
openAPK();
}
}
}
});
findViewById(R.id.back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO 自动生成的方法存根
VideoListActivity.this.finish();
}
});
curve3.setOnClickListener(view -> {
Intent intent = new Intent(VideoListActivity.this, DeviceMapActivity.class);
intent.putExtra("intentLat",intentLat);
intent.putExtra("intentLng",intentLng);
intent.putExtra("isShowTitle",true);
startActivity(intent);
});
}
private void initData() {
//mvideolist = VideoActivity.videolist;
Bundle bundle = getIntent().getExtras();
mvideolist = (ArrayList<Map<String, String>>) bundle.get("list");
aliasname = bundle.getString("aliasname");
user_control_power = bundle.getString("user_control_power");
site_control_power = bundle.getString("site_control_power");
netmode = bundle.getString("netmode");
}
protected void openAPK() {
// 首先判断SD卡是否可用
if (!FileUtils.getSDcard()) {
Toast.makeText(this, "外部存储不可用,此功能禁用", Toast.LENGTH_SHORT).show();
}
// 判断SD卡是否已安装
else if (!FileUtils.checkInstall(getApplicationContext(), package_name)) {
AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this);
builder.setTitle("提示").setMessage("未安装视频插件,是否安装?")
.setPositiveButton("安装", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 读取APK
readApk();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
//已安装应用,直接打开应用
//判断是否需要更新
PackageManager pm = context.getPackageManager();
try {
//通过包名获取已安装应用的信息,然后获取版本号。在与最新版本号对比是否需要进行更新。
PackageInfo info = pm.getPackageInfo(package_name, 1);
int code = info.versionCode;
if (curersioncode > code) {
//有新版本需要跟新
AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this);
builder.setTitle("提示").setMessage("视频插件需要更新,请点击安装!")
.setPositiveButton("安装", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 读取APK
readApk();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
//不需要更新,直接打开APK
startApk2();
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected void openAPK2() {
// 首先判断SD卡是否可用
if (!FileUtils.getSDcard()) {
Toast.makeText(this, "外部存储不可用,此功能禁用", Toast.LENGTH_SHORT).show();
}
// 判断SD卡是否已安装
else if (!FileUtils.checkInstall(getApplicationContext(), package_name2)) {
AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this);
builder.setTitle("提示").setMessage("未安装视频插件,是否安装?")
.setPositiveButton("安装", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 读取APK
readApk2();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
//已安装应用,直接打开应用
//判断是否需要更新
PackageManager pm = context.getPackageManager();
try {
//通过包名获取已安装应用的信息,然后获取版本号。在与最新版本号对比是否需要进行更新。
PackageInfo info = pm.getPackageInfo(package_name2, 1);
int code = info.versionCode;
if (curersioncode2 > code) {
//有新版本需要跟新
AlertDialog.Builder builder = new AlertDialog.Builder(VideoListActivity.this);
builder.setTitle("提示").setMessage("视频插件需要更新,请点击安装!")
.setPositiveButton("安装", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 读取APK
readApk2();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
AlertDialog dialog = builder.create();
dialog.show();
} else {
//不需要更新,直接打开APK
startApk3();
}
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
protected void readApk() {
InputStream in1 = null;
OutputStream out;
FileUtils fileUtils = new FileUtils();
AssetManager am = getAssets();
byte[] buffer = new byte[1024];
int read;
try {
in1 = am.open(APK_NAME);
File file = new File(fileUtils.getSDPATH() + APK_NAME);
file.createNewFile();
out = new FileOutputStream(file);
while ((read = in1.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.flush();
in1.close();
out.close();
} catch (IOException e) {
} finally {
try {
in1.close();
} catch (IOException e) {
}
}
installApk(APK_NAME);
}
protected void readApk2() {
InputStream in1 = null;
InputStream in2 = null;
InputStream in3 = null;
InputStream in4 = null;
InputStream in5 = null;
OutputStream out = null;
FileUtils fileUtils = new FileUtils();
AssetManager am = getAssets();
byte[] buffer = new byte[1024];
int read = 0;
try {
in1 = am.open("zxcv1.apk");
in2 = am.open("zxcv2.apk");
in3 = am.open("zxcv3.apk");
in4 = am.open("zxcv4.apk");
in5 = am.open("zxcv5.apk");
if (!fileUtils.isFileExist(APK_NAME2)
&& new File(fileUtils.getSDPATH() + APK_NAME2).length() < 1) {
File file = new File(fileUtils.getSDPATH() + APK_NAME2);
file.createNewFile();
out = new FileOutputStream(file);
while ((read = in1.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
while ((read = in2.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
while ((read = in3.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
while ((read = in4.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
while ((read = in5.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
out.flush();
in1.close();
in2.close();
in3.close();
in4.close();
in5.close();
out.close();
}
} catch (IOException e) {
} finally {
try {
in1.close();
in2.close();
in3.close();
in4.close();
in5.close();
} catch (IOException e) {
}
}
installApk(APK_NAME2);
}
protected void installApk(String apkName) {
//得到了Android外部存储目录
String fileName = Environment.getExternalStorageDirectory() + "/" + apkName;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileProvider", new File(fileName));
intent.setDataAndType(uri, "application/vnd.android.package-archive");
this.startActivity(intent);
}
protected void startApk2() {
ComponentName componentName = new ComponentName("com.hik.netsdk.SimpleDemo", "com.hik.netsdk.SimpleDemo.View.MainActivity");
Intent intent = new Intent();
// Intent intent = new Intent("chroya.foo");
Bundle bundle = new Bundle();
/* bundle.putString("serial", "811729242");//摄像机序列号
bundle.putString("VerifyCode", "CFEJRH");//摄像机验证码
bundle.putString("accessToken", "at.13zoz9dj48txpxtmbtdbxyp86yppa0kv-8377rzprmz-1ga3ixh-2csonzo9x");//访问令牌,7天过期。
*/
bundle.putString("appkey", Appkey);//Appkey
bundle.putString("serial", devserial);//摄像机序列号
bundle.putString("VerifyCode", VerifyCode);//摄像机验证码
bundle.putString("accessToken", accessToken);//访问令牌
bundle.putInt("cameraNo", channelName);//通道号
intent.putExtras(bundle);
intent.setComponent(componentName);
startActivity(intent);
}
protected void startApk3() {
ComponentName componentName = new ComponentName("com.example.funsdkdemo", "com.example.funsdkdemo.Xm4GSDKActivity");
Intent intent = new Intent();
// Intent intent = new Intent("chroya.foo");
Bundle bundle = new Bundle();
/* bundle.putString("serial", "811729242");//摄像机序列号
bundle.putString("VerifyCode", "CFEJRH");//摄像机验证码
bundle.putString("accessToken", "at.13zoz9dj48txpxtmbtdbxyp86yppa0kv-8377rzprmz-1ga3ixh-2csonzo9x");//访问令牌,7天过期。
*/
bundle.putString("xmip", xmip);
bundle.putString("xmport", xmport);
bundle.putString("xmusername", xmusername);
bundle.putString("xmpassword", xmpassword);
bundle.putString("devSn", devSn);
bundle.putString("xmmark", xmmark);
//System.out.println("---aaa---"+xmip+"--"+xmport+"--"+xmusername+"--"+xmpassword+"--"+devSn+"--"+xmmark);
intent.putExtras(bundle);
intent.setComponent(componentName);
startActivity(intent);
}
}
跨应用ysy1.apk的MainActivity:package com.hik.netsdk.SimpleDemo.View;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
// 添加 UnstableApi 注解支持
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.MediaItem;
import androidx.media3.common.Player;
import androidx.media3.common.PlaybackException;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DefaultHttpDataSource;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.hls.HlsMediaSource;
import androidx.media3.exoplayer.source.MediaSource;
import com.hik.netsdk.SimpleDemo.R;
import com.videogo.openapi.EZConstants;
import com.videogo.openapi.EZOpenSDK;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
// 在类级别添加 @UnstableApi 注解
@UnstableApi
public class MainActivity extends AppCompatActivity implements SurfaceHolder.Callback {
// 核心参数
private String mDeviceSerial;
private String mVerifyCode;
private int mCameraNo = 1;
private boolean isEzDevice = false;
// 萤石云相关参数
private String mAppKey = "a794d58c13154caeb7d2fbb5c3420c65";
private String mAccessToken = "";
// UI组件
private SurfaceView mPreviewSurface;
private SurfaceHolder mSurfaceHolder;
private Toolbar m_toolbar;
private ProgressBar mProgressBar;
private RelativeLayout mControlLayout;
private ImageButton mRotateButton;
// 播放器相关
private ExoPlayer mExoPlayer;
private String mPlaybackUrl;
private final OkHttpClient mHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.build();
// 播放器状态监听器
private final Player.Listener mPlayerListener = new Player.Listener() {
@Override
public void onPlaybackStateChanged(int state) {
switch (state) {
case Player.STATE_READY:
mProgressBar.setVisibility(View.GONE);
Log.d("ExoPlayer", "播放准备就绪");
break;
case Player.STATE_BUFFERING:
mProgressBar.setVisibility(View.VISIBLE);
Log.d("ExoPlayer", "缓冲中...");
break;
case Player.STATE_ENDED:
Log.d("ExoPlayer", "播放结束");
break;
case Player.STATE_IDLE:
Log.d("ExoPlayer", "空闲状态");
break;
}
}
@Override
public void onPlayerError(PlaybackException error) {
Log.e("ExoPlayer", "播放错误: " + error.getMessage());
handleError("播放错误: " + error.getMessage(), -1);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activitymain);
// 初始化UI组件
initUIComponents();
// 获取启动参数
parseIntentParams();
// 初始化SDK
initSDK();
// 参数校验
if (mDeviceSerial == null || mDeviceSerial.isEmpty()) {
showErrorAndFinish("设备序列号不能为空");
return;
}
Log.d("MainActivity", "onCreate完成: isEzDevice=" + isEzDevice);
}
@SuppressLint("WrongViewCast")
private void initUIComponents() {
// 基础UI
m_toolbar = findViewById(R.id.titlename);
setSupportActionBar(m_toolbar);
// 预览相关UI
mPreviewSurface = findViewById(R.id.realplay_sv);
mSurfaceHolder = mPreviewSurface.getHolder();
mSurfaceHolder.addCallback(this);
mSurfaceHolder.setFormat(PixelFormat.TRANSLUCENT);
mProgressBar = findViewById(R.id.liveProgressBar);
mControlLayout = findViewById(R.id.rl_control);
mRotateButton = findViewById(R.id.ib_rotate2);
// 设置旋转按钮点击事件
mRotateButton.setOnClickListener(v -> changeScreen());
if (m_toolbar != null) {
m_toolbar.setVisibility(View.GONE);
}
// 初始化控制按钮
initControlButtons();
Log.d("UI", "UI组件初始化完成");
}
private void parseIntentParams() {
// 获取Intent参数
Intent intent = getIntent();
isEzDevice = true; // 只支持萤石设备
mAccessToken = intent.getStringExtra("accessToken");
// 优先使用bundle
Bundle bundle = intent.getExtras();
if (bundle != null) {
mDeviceSerial = bundle.getString("devSn");
mVerifyCode = bundle.getString("verifyCode");
mCameraNo = bundle.getInt("cameraNo", 1);
}
// 兼容直接Extra方式
if (mDeviceSerial == null) mDeviceSerial = intent.getStringExtra("devSn");
if (mVerifyCode == null) mVerifyCode = intent.getStringExtra("verifyCode");
if (mCameraNo == 0) mCameraNo = intent.getIntExtra("cameraNo", 1);
Log.d("Params", "设备序列号: " + mDeviceSerial + ", 通道号: " + mCameraNo);
}
private void initSDK() {
try {
// 使用反射检查初始化状态
boolean isInitialized = false;
try {
EZOpenSDK instance = EZOpenSDK.getInstance();
if (instance != null) {
isInitialized = true;
}
} catch (Exception e) {
isInitialized = false;
}
// 未初始化时进行初始化
if (!isInitialized) {
EZOpenSDK.initLib(getApplication(), mAppKey);
Log.d("EZSDK", "萤石SDK初始化完成");
}
// 设置AccessToken
if (mAccessToken != null && !mAccessToken.isEmpty()) {
EZOpenSDK.getInstance().setAccessToken(mAccessToken);
Log.d("EZToken", "AccessToken设置成功");
} else {
Log.w("EZToken", "AccessToken缺失!");
}
} catch (Exception e) {
Log.e("EZSDK", "萤石SDK初始化失败", e);
handleError("萤石SDK初始化失败: " + e.getMessage(), -1);
}
}
private void initControlButtons() {
// 云台控制按钮
findViewById(R.id.ptz_top_btn).setOnClickListener(v -> controlPTZ("UP"));
findViewById(R.id.ptz_bottom_btn).setOnClickListener(v -> controlPTZ("DOWN"));
findViewById(R.id.ptz_left_btn).setOnClickListener(v -> controlPTZ("LEFT"));
findViewById(R.id.ptz_right_btn).setOnClickListener(v -> controlPTZ("RIGHT"));
// 变焦控制
findViewById(R.id.focus_add).setOnClickListener(v -> controlZoom("ZOOM_IN"));
findViewById(R.id.foucus_reduce).setOnClickListener(v -> controlZoom("ZOOM_OUT"));
// 水平布局控制按钮
findViewById(R.id.ptz_top_btn2).setOnClickListener(v -> controlPTZ("UP"));
findViewById(R.id.ptz_bottom_btn2).setOnClickListener(v -> controlPTZ("DOWN"));
findViewById(R.id.ptz_left_btn2).setOnClickListener(v -> controlPTZ("LEFT"));
findViewById(R.id.ptz_right_btn2).setOnClickListener(v -> controlPTZ("RIGHT"));
Log.d("Controls", "控制按钮初始化完成");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.d("Surface", "Surface created");
// 获取播放地址并开始播放
new Thread(this::fetchPlaybackUrl).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.d("Surface", "Surface changed: " + width + "x" + height);
if (mExoPlayer != null) {
mExoPlayer.setVideoSurfaceHolder(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d("Surface", "Surface destroyed");
stopPreview();
}
// ======================== 播放地址获取与播放 ========================
private void fetchPlaybackUrl() {
try {
// 构建请求参数
JSONObject params = new JSONObject();
params.put("accessToken", mAccessToken);
params.put("deviceSerial", mDeviceSerial);
params.put("channelNo", mCameraNo);
params.put("protocol", 2); // 使用HLS协议
if (mVerifyCode != null && !mVerifyCode.isEmpty()) {
params.put("code", mVerifyCode);
}
params.put("expireTime", 7200); // 2小时有效期
// 创建请求体
RequestBody body = RequestBody.create(
MediaType.parse("application/json"),
params.toString()
);
// 创建请求
Request request = new Request.Builder()
.url("https://open.ys7.com/api/lapp/v2/live/address/get")
.post(body)
.build();
// 执行请求
try (Response response = mHttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
handleError("获取播放地址失败: " + response.code(), response.code());
return;
}
// 解析响应
String responseBody = response.body().string();
JSONObject json = new JSONObject(responseBody);
if ("200".equals(json.getString("code"))) {
JSONObject data = json.getJSONObject("data");
mPlaybackUrl = data.getString("url");
Log.d("PlaybackURL", "获取到播放地址: " + mPlaybackUrl);
// 在主线程初始化播放器
runOnUiThread(this::initExoPlayer);
} else {
handleError("API错误: " + json.getString("msg"), json.getInt("code"));
}
}
} catch (JSONException | IOException e) {
Log.e("FetchURL", "获取播放地址异常", e);
handleError("获取播放地址异常: " + e.getMessage(), -1);
}
}
private void initExoPlayer() {
// 释放现有播放器
if (mExoPlayer != null) {
mExoPlayer.release();
}
// 创建播放器
mExoPlayer = new ExoPlayer.Builder(this).build();
mExoPlayer.addListener(mPlayerListener);
// 设置视频渲染器
mExoPlayer.setVideoSurfaceHolder(mSurfaceHolder);
// 创建媒体源
DataSource.Factory dataSourceFactory = new DefaultHttpDataSource.Factory();
MediaSource mediaSource = new HlsMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(Uri.parse(mPlaybackUrl)));
// 准备播放
mExoPlayer.setMediaSource(mediaSource);
mExoPlayer.prepare();
mExoPlayer.setPlayWhenReady(true);
mProgressBar.setVisibility(View.VISIBLE);
Log.d("ExoPlayer", "播放器初始化完成,开始播放");
}
// ======================== 萤石云控制方法 ========================
private int mapDirection(String direction) {
switch (direction) {
default: return -1;
}
}
private void controlPTZ(String direction) {
int directionCode = mapDirection(direction);
if (directionCode == -1) return;
// 控制逻辑实现
}
private void controlZoom(String command) {
String direction = "ZOOM_IN".equals(command) ? "ZOOM_IN" : "ZOOM_OUT";
controlPTZ(direction);
}
// ======================== 通用功能方法 ========================
public void changeScreen(View view) {
changeScreen();
}
private void changeScreen() {
if (mControlLayout.getVisibility() == View.VISIBLE) {
mControlLayout.setVisibility(View.GONE);
} else {
mControlLayout.setVisibility(View.VISIBLE);
}
}
private void handleError(String message, int errorCode) {
String fullMessage = message + " (错误码: " + errorCode + ")";
// 萤石云特有错误码处理
switch (errorCode) {
case 400001:
fullMessage = "AccessToken无效";
break;
case 400002:
fullMessage = "设备不存在";
break;
case 400007:
fullMessage = "设备不在线";
break;
case 400034:
fullMessage = "验证码错误";
break;
case 400035:
fullMessage = "设备已被自己添加";
break;
case 400036:
fullMessage = "设备已被别人添加";
break;
default:
fullMessage = "萤石云错误: " + errorCode;
}
new AlertDialog.Builder(this)
.setTitle("预览失败")
.setMessage(fullMessage)
.setPositiveButton("确定", (d, w) -> finish())
.setCancelable(false)
.show();
}
private void showErrorAndFinish(String message) {
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
new Handler().postDelayed(this::finish, 3000);
}
private void stopPreview() {
if (mExoPlayer != null) {
mExoPlayer.release();
mExoPlayer = null;
Log.d("Preview", "预览已停止");
}
}
@Override
protected void onDestroy() {
super.onDestroy();
stopPreview();
Log.d("Lifecycle", "onDestroy");
}
@Override
protected void onPause() {
super.onPause();
if (mExoPlayer != null) {
mExoPlayer.setPlayWhenReady(false);
Log.d("Lifecycle", "暂停播放");
}
}
@Override
protected void onResume() {
super.onResume();
if (mExoPlayer != null) {
mExoPlayer.setPlayWhenReady(true);
Log.d("Lifecycle", "恢复播放");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main_opt, menu);
return true;
}
}