程序员人生 网站导航

[置顶] 第一个Android TV Launcher开源项目

栏目:综合技术时间:2015-04-13 08:53:37

Android TV Launcher开源项目

这个项目是机顶盒桌面,用来播放视频、显示图片、利用管理和其他针对机顶盒产品的设置。目前git和CSDN code上面都没有类似的开源项目,正好本人最近在开发类似产品,网上类似研究还非常少,完全自己实现还是比较困难。所以就把目前的项目开源出来,也有益于其他人少走弯路。
git项目地址
CSDN code项目地址

项目框架结构

Launcher项目结构
UI、adapter、实体类、图片cache、网络层。
这个层级关系还是和大部份项目是类似的。

功能模块的详细实现方式

这个部份主要讲1下机顶盒Launcher实现的几个难点,如还有其他问题请留言。

app管理

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值来监听全局的消息通知。 // 比如,当装备停止被搜索以后,该消息可以被系统通知
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐