Tv App Develop of EuInstaller

1:Euinstaller 框架

这里写图片描述

2: develop tips

  • WizardScreenManager,如何管理多个View
    在installer的安装过程中,会选择国家,制式,operator,等等,如何在这些screen间前进和后退。如下图所示:
    screen的前进和后退
    类图如下:
    这里写图片描述
    code流程图:
    这里写图片描述
    在启动InstallerWizardActivity,新建一个WizardScreenManager实例,
// launch normal wizard installation
wizardScreenManager = new WizardScreenManager(WizardFlow.NORMAL_INSTALLTION,parentContainerView, ctx);
wizardScreenManager.startWizardFlow();

紧接着根据传入的wizardType去启动wizard,在启动wizard时,会根据RequestScreen创建一个HashMap,和一个Stack。

    public void startWizardFlow() {
        Log.d(TAG, "startWizardFlow");
        wizardScreenMapping = new HashMap<ScreenRequest, IWizardScreen>();
        mScreenRequestStack = new Stack<WizardScreenManager.ScreenRequest>();
        if (currentWizardFlow == WizardFlow.NORMAL_INSTALLTION) {
            mLaunchItem = ScreenRequest.START_SCREEN;
        } else if (currentWizardFlow == WizardFlow.NETWORK_UPDATE) {
            mLaunchItem = ScreenRequest.NWK_UPDATING_SCREEN;
        } else if (currentWizardFlow == WizardFlow.CAM_URGENT_INSTALL) {
            nwrap.selectCamBasedInstallation();
            nwrap.setCurrentInstallationMode(NativeAPIEnums.InstallationMode.CAM_INSTALLATION);
            mLaunchItem = ScreenRequest.SEARCHING_SCREEN;
        }

        launchScreen(mLaunchItem, null);
    }

最后去LaunchSreen,会判断当前的screen是否有创建,并将它加到Hashmap中,并且将当前的screen入栈。

    public void launchScreen(ScreenRequest launchItem, ScreenRequest requestedByScreen) {

        wizardScreenMapping.put(launchItem, createWizardScreen(launchItem));

        // first get the corresponding wizard screen object
        targetWizardScreen = wizardScreenMapping.get(launchItem);

        // call exit routine of the existing screen with fade away animation
        if (requestedByScreen != null) {    // its the first screen
            if (wizardScreenMapping.containsKey(requestedByScreen)) {
                wizardScreenMapping.get(requestedByScreen).exitScreen();
                wizardScreenMapping.get(requestedByScreen).detachView();
            }
        }

        // remove all existing views
        parentView.removeAllViews();

        // push to backstack
        mScreenRequestStack.push(mLaunchItem);

        // current requested screen
        mLaunchItem = launchItem;

        // add requested view to viewgroup
            parentView.addView(targetWizardScreen.getExistingLayout());
        //start fade-in animation for the added view

        targetWizardScreen.attachView();

        // call initScreen
        targetWizardScreen.initScreen();
    }

根据LauchItem创建对应的screen

private IWizardScreen createWizardScreen(ScreenRequest launchItem) {
        IWizardScreen targetWizardScreen = null;

        switch (launchItem) {
            case ANTENNA_SCREEN:
                targetWizardScreen = new AntennaCableScreen(mContext);
                break;
            case COUNTRY_SCREEN:
                targetWizardScreen = new CountryScreen(mContext);
                break;
                ......
}
  • HandleActionList

    在install channel过程中,会分几个阶段,比如,ScanPrepare,ScanDVBT,ScanDVBC,TvProviderCheck等等,当在执行这些Action时,如何确保这些ScanAction有序的执行。
    首先定义一个ScanAction的类和可能会执行到的Scan Type

    private enum ActionType
    {
        ScanDVBT,
                ScanDVBTMpegOnly,
                ScanDVBC,
                ScanDVBCAdvanced,
                ScanDVBCQuickAfterAdv,
                ScanAnalog,
                ScanCAM,
                ChListCheck,
                CamChListCheck,
                ChListArrange,
                ScannerCheck,
                ScanPrepare,
                ScanCamPrepare,
                ScanDtrPrepare,
                TvProviderCheck
    }

    private class ScanAction {
        public ActionType meAction;
        public int miInstMode;
        public int miStartProg;
        public int miProgFactor;

        public ScanAction(ActionType aeAction, int aiInstMode, int aiStartProgress, int aiProgressFactor) {
            meAction = aeAction;
            miInstMode = aiInstMode;
            miStartProg = aiStartProgress;
            miProgFactor = aiProgressFactor;
        }

        public ScanAction(ActionType aeAction) {
            meAction = aeAction;
            miInstMode = InsEventConst.InstallationModeNone;
            miStartProg = 0;
            miProgFactor = 1;
        }
    }

然后,定义一个ScanAction的数组,将需要执行的Scan Type放到list里。

private ArrayList<ScanAction> mvActionList = new ArrayList<ScanAction>();

mvActionList.add(new ScanAction(ActionType.ScanPrepare, mode, 0, 1));
mvActionList.add(new ScanAction(ActionType.ScannerCheck, mode, 0, 1));
mvActionList.add(new ScanAction(ActionType.ScanDVBT, mode, scanIndex * 100 / scanStep, scanStep));
mvActionList.add(new ScanAction(ActionType.TvProviderCheck, mode, 0, 1));
mvActionList.add(new ScanAction(ActionType.ChListCheck));

在开始Scan的时候,去执行执行这些Action,新建一个Thread来执行。

    private void doHandleActionList() {
        //Log.d(TAG, "doHandleActionList INST_SERVICE");
        Thread thread = new Thread(
                new Runnable() {
                    @Override
                    public void run() {
                        handleActionList();
                    }
                }
        );
        thread.start();
    }

接着来看handleActionList,如果list数组size为空,表示先前加入到Action List中的内容已全部执行完毕。同时,没执行一次的时候,将数组中第一个Action删除掉。

private void handleActionList() {
        Logger.LOGD(TAG, "handleActionList");

        if (mvActionList.size() == 0) {
            Log.d(TAG, "Action list is empty now");
            ntf.notifyAllObservers(EventIDs.EVENT_INST_COMPLETED, "");
            return;
        }

        ScanAction fAction = mvActionList.remove(0);

        Log.d(TAG, "handleActionList() " + fAction.meAction);
        switch (fAction.meAction) {
            case ScanDVBT:
            case ScanDVBTMpegOnly:
                Sleep(1500);
                scanDVBT(fAction);
                break;
            case ScanDVBC:
            ......
    }
  • IScanner
    在Scan过程中,分Scan DVBT, DVBC, ATV, NTSC 这几种scan方式,但是这些都必须通过MTK TVAPI来实现,因此可以将常用的方法抽象出一个接口,其他的类来实现这个接口,就可以优化code结构。
    Scan 类图如下所示:
    这里写图片描述

初始化IScanner对象,在执行scan时,可将scan Runnable post到scan 线程,

private IScanner mMTKScanner = null;
mMTKScanner = new DVBTScanner(fScanParam)
mMtkScanHandler.postDelayed(mMtkFullScan, 0);
    private Runnable mMtkFullScan = new Runnable() {
        boolean bRet = false;

        @Override
        public void run() {
            if (mMTKScanner != null) {
                bRet = mMTKScanner.fullScan();
                if (false == bRet) {
                    Log.d(TAG, "mMtkFullScan fail.");
                    if (mMtkScanHandler != null) {
                        Log.d(TAG, "mMtkFullScan try again.");
                        mMtkScanHandler.postDelayed(mMtkFullScan, 3000);
                    }
                }
                Log.d(TAG, "mMtkFullScan ok.");
            }
        }
    };
  • 文件存储,Searalizable

    当TV有完整做完一次full-scan,在下次scan的时候,希望能得到上次scan过程选择的country,mediatype,operator时,该如何将上次选择的值保存下来,这里用到了Searilizable。
    类图关系如下:
    这里写图片描述
    在DVBSettings 定义需要保存的值。

class DVBSettings implements Serializable {
    private static final long serialVersionUID = 1L;
    int ScanMode = MwDataTypes.InstallerConstants.InstallationStyleQuick;                               /* Quick/Full Scan */
    int SymbolRateMode = MwDataTypes.InstallerConstants.AutomaticValue;                         /* Auto/Manual */
    int[] SymbolRate = null;           /* Array of SymbolRates */
    int NetworkIDMode = MwDataTypes.InstallerConstants.AutomaticValue;                          /* Auto/Manual */
    int NetworkID = -1;                              /* Can be any valid networkId */
    int NetworkFrequencyMode = MwDataTypes.InstallerConstants.AutomaticValue;                   /* Auto/Manual */
    int[] NetworkFrequency = null;   /* List of frequencies fixed per country */
    int ModulationMode = MwDataTypes.InstallerConstants.AutomaticValue;                         /* Auto/Manual */
    int[] Modulation;       /* List of Mod types fixed per country */
    int DigitalOption = 1;                          /* ON - DVBC_Lite OFF - NO DVBC */
    int[] UserSymbolRate;
    int FreqStepSize = MwDataTypes.InstallerConstants.DVBCStepSize8;
    int InstalledCity = -1;                          /* For china, as NVM is not avbl. hence flash approach followed */
    int InstalledONID = -1;
    int ScrambledState = -1;
    int NetworkOperator = -1;                        /* for Netherlands Cable */
    int LCNSorting = 0;
    int DualAnalogPass = 0;
    int DTTScanonAnalog = 0;
    int LCNOption = 1;
    int InstalledCountry = -1;

    public DVBSettings() {
    }
}

先定义一个DVBSettings 的Object

private DVBSettings mSettingPersistent;

当扫台结束时,将数据写到mSettingPersistent

public void CommitPreferred() {
        FileOutputStream fos = null;
        ObjectOutputStream oos = null;

        Log.d(TAG, "CommitPreferred()");

        CopyTemporaryToPersistent();

        try {
            fos = mActivityInstance.openFileOutput(gsFileName, Context.MODE_PRIVATE);
            oos = new ObjectOutputStream(fos);

            oos.writeObject(mSettingPersistent);
        } catch (FileNotFoundException e) {
            Log.d(TAG, "The file of AttributeStore is not found.");
        } catch (StreamCorruptedException e) {
            Log.d(TAG, "Writing of AttributeStore file fail. " + e.toString());
        } catch (IOException e) {
            Log.d(TAG, "Writing of AttributeStore file fail. " + e.toString());
        }

        try {
            if (oos != null)
                oos.close();
        } catch (IOException e) {
        }

        try {
            if (fos != null)
                fos.close();
        } catch (IOException e) {
        }
    }

在下次scan时,将上次scan的值load出来

    private DVBSettings loadPresistentSettings() {
        DVBSettings fSettings = null;
        FileInputStream fis = null;
        ObjectInputStream ois = null;

        Log.d(TAG, "loadPresistentSettings()");

        try {
            fis = mActivityInstance.openFileInput(gsFileName);
            ois = new ObjectInputStream(fis);

            fSettings = (DVBSettings) ois.readObject();
        } catch (FileNotFoundException e) {
            Log.d(TAG, "The file of AttributeStore is not found.");
        } catch (StreamCorruptedException e) {
            Log.d(TAG, "Loading of AttributeStore file fail. " + e.toString());
        } catch (IOException e) {
            Log.d(TAG, "Loading of AttributeStore file fail. " + e.toString());
        } catch (ClassNotFoundException e) {
            Log.d(TAG, "AttributeStore can not be found in the file.");
        }

        try {
            if (ois != null)
                ois.close();
        } catch (IOException e) {
        }

        try {
            if (fis != null)
                fis.close();
        } catch (IOException e) {
        }

        return fSettings;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值