这个项目是机顶盒桌面,用来播放视频、显示图片、利用管理和其他针对机顶盒产品的设置。目前git和CSDN code上面都没有类似的开源项目,正好本人最近在开发类似产品,网上类似研究还非常少,完全自己实现还是比较困难。所以就把目前的项目开源出来,也有益于其他人少走弯路。
git项目地址
CSDN code项目地址
UI、adapter、实体类、图片cache、网络层。
这个层级关系还是和大部份项目是类似的。
这个部份主要讲1下机顶盒Launcher实现的几个难点,如还有其他问题请留言。
1.扫描可启动的利用
由于原项目效果图不符合开源要求所以去掉了。
public ArrayList<AppBean> getLaunchAppList() {
PackageManager localPackageManager = mContext.getPackageManager();
Intent localIntent = new Intent("android.intent.action.MAIN");
localIntent.addCategory("android.intent.category.LAUNCHER");
List<ResolveInfo> localList = localPackageManager.queryIntentActivities(localIntent, 0);
ArrayList<AppBean> localArrayList = null;
Iterator<ResolveInfo> localIterator = null;
if (localList != null) {
localArrayList = new ArrayList<AppBean>();
localIterator = localList.iterator();
}
while (true) {
if (!localIterator.hasNext())
break;
ResolveInfo localResolveInfo = (ResolveInfo) localIterator.next();
AppBean localAppBean = new AppBean();
localAppBean.setIcon(localResolveInfo.activityInfo.loadIcon(localPackageManager));
localAppBean.setName(localResolveInfo.activityInfo.loadLabel(localPackageManager).toString());
localAppBean.setPackageName(localResolveInfo.activityInfo.packageName);
localAppBean.setDataDir(localResolveInfo.activityInfo.applicationInfo.publicSourceDir);
localAppBean.setLauncherName(localResolveInfo.activityInfo.name);
String pkgName = localResolveInfo.activityInfo.packageName;
PackageInfo mPackageInfo;
try {
mPackageInfo = mContext.getPackageManager().getPackageInfo(pkgName, 0);
if ((mPackageInfo.applicationInfo.flags & mPackageInfo.applicationInfo.FLAG_SYSTEM) > 0) {//系统预装
localAppBean.setSysApp(true);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
String noSeeApk = localAppBean.getPackageName();
// 屏蔽1些apk
if (!noSeeApk.equals("com.cqsmiletv") && !noSeeApk.endsWith("com.starcor.hunan") && !noSeeApk.endsWith("com.tcl.matrix.tventrance")) {
localArrayList.add(localAppBean);
}
}
return localArrayList;
}
//接收安装广播
if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
String packageName = intent.getDataString();
List<ResolveInfo> list = Tools.findActivitiesForPackage(context, packageName);
ResolveInfo info = list.get(0);
PackageManager localPackageManager = context.getPackageManager();
AppBean localAppBean = new AppBean();
localAppBean.setIcon(info.activityInfo.loadIcon(localPackageManager));
localAppBean.setName(info.activityInfo.loadLabel(localPackageManager).toString());
localAppBean.setPackageName(info.activityInfo.packageName);
localAppBean.setDataDir(info.activityInfo.applicationInfo.publicSourceDir);
mAppList.add(localAppBean);
}
上面的第1个代码模块主要是扫描机顶盒上面安装了哪些利用,把信息填到实体类里面去,还可以根据自己产品要求屏蔽1些apk。
第2个代码块是检测安装广播,根据需要更新数据。
2.扫描可卸载的利用
public ArrayList<AppBean> getUninstallAppList() {
PackageManager localPackageManager = mContext.getPackageManager();
Intent localIntent = new Intent("android.intent.action.MAIN");
localIntent.addCategory("android.intent.category.LAUNCHER");
List<ResolveInfo> localList = localPackageManager.queryIntentActivities(localIntent, 0);
ArrayList<AppBean> localArrayList = null;
Iterator<ResolveInfo> localIterator = null;
if (localList != null) {
localArrayList = new ArrayList<AppBean>();
localIterator = localList.iterator();
}
while (true) {
if (!localIterator.hasNext())
break;
ResolveInfo localResolveInfo = (ResolveInfo) localIterator.next();
AppBean localAppBean = new AppBean();
localAppBean.setIcon(localResolveInfo.activityInfo.loadIcon(localPackageManager));
localAppBean.setName(localResolveInfo.activityInfo.loadLabel(localPackageManager).toString());
localAppBean.setPackageName(localResolveInfo.activityInfo.packageName);
localAppBean.setDataDir(localResolveInfo.activityInfo.applicationInfo.publicSourceDir);
String pkgName = localResolveInfo.activityInfo.packageName;
PackageInfo mPackageInfo;
try {
mPackageInfo = mContext.getPackageManager().getPackageInfo(pkgName, 0);
if ((mPackageInfo.applicationInfo.flags & mPackageInfo.applicationInfo.FLAG_SYSTEM) > 0) {//系统预装
localAppBean.setSysApp(true);
} else {
localArrayList.add(localAppBean);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
return localArrayList;
}
//接收卸载广播
if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
String receiverName = intent.getDataString();
receiverName = receiverName.substring(8);
AppBean appBean;
for(int i=0;i<mAppList.size();i++){
appBean = mAppList.get(i);
String packageName = appBean.getPackageName();
if(packageName.equals(receiverName)){
mAppList.remove(i);
adapter.notifyDataSetChanged();
}
}
}
由于系统预装的按常理方法是没法卸载的,应当屏蔽掉。卸载的时候根据广播返回标志更新数据。
3.自启动管理
public ArrayList<AppBean> getAutoRunAppList() {
PackageManager localPackageManager = mContext.getPackageManager();
Intent localIntent = new Intent("android.intent.action.MAIN");
localIntent.addCategory("android.intent.category.LAUNCHER");
List<ResolveInfo> localList = localPackageManager.queryIntentActivities(localIntent, 0);
ArrayList<AppBean> localArrayList = null;
Iterator<ResolveInfo> localIterator = null;
if (localList != null) {
localArrayList = new ArrayList<AppBean>();
localIterator = localList.iterator();
}
while (true) {
if (!localIterator.hasNext())
break;
ResolveInfo localResolveInfo = localIterator.next();
AppBean localAppBean = new AppBean();
localAppBean.setIcon(localResolveInfo.activityInfo.loadIcon(localPackageManager));
localAppBean.setName(localResolveInfo.activityInfo.loadLabel(localPackageManager).toString());
localAppBean.setPackageName(localResolveInfo.activityInfo.packageName);
localAppBean.setDataDir(localResolveInfo.activityInfo.applicationInfo.publicSourceDir);
String pkgName = localResolveInfo.activityInfo.packageName;
String permission = "android.permission.RECEIVE_BOOT_COMPLETED";
try {
PackageInfo mPackageInfo = mContext.getPackageManager().getPackageInfo(pkgName, 0);
if ((PackageManager.PERMISSION_GRANTED == localPackageManager.checkPermission(permission, pkgName)) && !((mPackageInfo.applicationInfo.flags & mPackageInfo.applicationInfo.FLAG_SYSTEM) > 0)) {
localArrayList.add(localAppBean);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
}
return localArrayList;
}
扫描利用权限查看是不是是自启动app,返回所有自启动app。
public boolean manageBoot(String pkg,boolean able) {
Process process = null;
DataOutputStream dos = null;
String command = null;
try {
process = Runtime.getRuntime().exec("su");
dos = new DataOutputStream(process.getOutputStream());
dos.flush();
command = "export LD_LIBRARY_PATH=/vendor/lib:/system/lib
";
dos.writeBytes(command);
//(有些cls含有$,需要处理1下,不然会制止失败,比如微信)
//但是获得利用是不是允许或制止开机启动的时候就不用途理cls,否则得不到状态值
// cls = cls.replace("$", "$");
// command = "pm disable " + pkg + "/" + cls + "
";
if(able){
command = "pm enable " + pkg;
}else{
command = "pm disable " + pkg;
}
dos.writeBytes(command);
dos.writeBytes("exit " + "
");
dos.flush();
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
int exitValue = process.exitValue();
try {
if (exitValue == 0) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (process != null) {
process.destroy();
}
}
return false;
}
制止利用自启动,需要有root权限。
1.WiFi
扫描附近WiFi
public void StartScan() {
mWifiManager.startScan();
// 得到扫描结果
mWifiList = mWifiManager.getScanResults();
// 得到配置好的网络连接
mWifiConfigurations = mWifiManager.getConfiguredNetworks();
Log.v("mWifiManager", mWifiManager+"");
Log.v("mWifiList", mWifiList+"");
Log.v("mWifiConfigurations", mWifiConfigurations+"");
}
根据WiFi几种加密方式配置wificonfiguration
public WifiConfiguration CreatConfiguration(String SSID, String Password,
int Type) {
WifiConfiguration configuration = new WifiConfiguration();
configuration.allowedAuthAlgorithms.clear();
configuration.allowedGroupCiphers.clear();
configuration.allowedKeyManagement.clear();
configuration.allowedPairwiseCiphers.clear();
configuration.allowedProtocols.clear();
configuration.SSID = """ + SSID + """;
WifiConfiguration tempConfiguration = IsExits(SSID, mWifiManager);
if (tempConfiguration != null) {
mWifiManager.removeNetwork(tempConfiguration.networkId);
}
// WIFICIPHER_NOPASS
if (Type == 1) {
configuration.wepKeys[0] = "";
configuration.allowedKeyManagement
.set(WifiConfiguration.KeyMgmt.NONE);
configuration.wepTxKeyIndex = 0;
}
// WIFICIPHER_WEP
if (Type == 2) {
configuration.hiddenSSID = true;
configuration.wepKeys[0] = """ + Password + """;
configuration.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.SHARED);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.CCMP);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.TKIP);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.WEP40);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.WEP104);
configuration.allowedKeyManagement
.set(WifiConfiguration.KeyMgmt.NONE);
configuration.wepTxKeyIndex = 0;
}
// WIFICIPHER_WPA
if (Type == 3) {
configuration.preSharedKey = """ + Password + """;
configuration.hiddenSSID = true;
configuration.allowedAuthAlgorithms
.set(WifiConfiguration.AuthAlgorithm.OPEN);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.TKIP);
configuration.allowedKeyManagement
.set(WifiConfiguration.KeyMgmt.WPA_PSK);
configuration.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.TKIP);
configuration.allowedGroupCiphers
.set(WifiConfiguration.GroupCipher.CCMP);
configuration.allowedPairwiseCiphers
.set(WifiConfiguration.PairwiseCipher.CCMP);
configuration.status = WifiConfiguration.Status.ENABLED;
}
return configuration;
}
根据上面得到的信息用WiFimanager连接网络,返回的信息可判断是不是连接成功。
public int AddNetwork(WifiConfiguration configuration) {
int configurationId = mWifiManager.addNetwork(configuration);
boolean b = mWifiManager.enableNetwork(configurationId, true);
return configurationId;
}
2.蓝牙
在机顶盒中蓝牙经常使用于蓝牙遥控、键盘、游戏手柄。
注册蓝牙状态广播(连接、正在连接、已连接)
IntentFilter intent = new IntentFilter();
// 用BroadcastReceiver来获得搜索结果
intent.addAction(BluetoothDevice.ACTION_FOUND);
//每当扫描模式变化的时候,利用程序可以为通过ACTION_SCAN_MODE_CHANGED值来监听全局的消息通知。
// 比如,当装备停止被搜索以后,该消息可以被系统通知