Android TIF 應用實例-T960 應用添加後臺TvView過程及代碼

項目需要,有個背景透明的應用後臺需要播放TV,之前是使用LiveTv在後臺播放,由於嚴重依賴於LiveTV,使用起來很不方便,如果能直接在這個應用中播放TV,那就好了。於是,嘗試在後臺添加TvView,現記錄使用過程。應用起來比較簡單。

一、原菜單不變,僅僅添加TvView控件。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:ctvui="http://schemas.android.com/apk/res-auto"

    android:id="@+id/main_bg"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:background="@color/black_six" >

    <android.media.tv.TvView

        android:id="@+id/tv_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent"/>

....

</FrameLayout>

二、代碼部分,僅TvView相關部分

public class MainActivity extends Activity {

import android.database.IContentObserver;

import android.media.tv.TvContract;

import android.media.tv.TvContract.Channels;

import android.media.tv.TvInputInfo;

import android.media.tv.TvInputManager;

import android.media.tv.TvTrackInfo;

import android.media.tv.TvView;

import com.cultraview.launcher.view.BlockScreenView;

//import com.droidlogic.app.SystemControlManager;

import com.droidlogic.app.tv.ChannelInfo;

import com.droidlogic.app.tv.DroidLogicTvUtils;

import com.droidlogic.app.tv.TvControlManager;

import com.droidlogic.app.tv.TvDataBaseManager;

...

private TvView mTvView;

    private String mTvInputId;

    private Uri mChannelUri;

    private boolean isRadioChannel = false;

    private TvInputManager mTvInputManager;

    private TvInputChangeCallback mTvInputChangeCallback;

    private TvDataBaseManager mTvDataBaseManager;

    private ChannelObserver mChannelObserver;

    private static final int TV_MSG_PLAY_TV                    = 0;

    private static final int TV_MSG_RUN_STOP                   = 1;

    private static final int TV_MSG_RUN_START                  = 2;

//private SystemControlManager mSystemControlManager;

    private boolean isFirst = false;

 

mTvView = (TvView)findViewById(R.id.tv_view);

 

    @Override

protected void onStart() {

// TODO 自動生成的方法存根

    super.onStart();

          mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);

    mTvInputChangeCallback = new TvInputChangeCallback();

          mTvInputManager.registerCallback(mTvInputChangeCallback, new Handler());

          mChannelObserver = new ChannelObserver();

          getContentResolver().registerContentObserver(Channels.CONTENT_URI, true, mChannelObserver);

          mTvView.setVisibility(View.VISIBLE);

          //mTvHandler.sendEmptyMessage(TV_MSG_PLAY_TV);

          mTvHandler.sendEmptyMessageDelayed(TV_MSG_PLAY_TV, 1000);

}

     @Override

protected void onStop() {

// TODO 自動生成的方法存根

super.onStop();

releaseTvView();

}

private void releaseTvView() {

        mTvView.setVisibility(View.GONE);

        mTvView.reset();

}

@Override

protected void onDestroy() {

    super.onDestroy();

    Log.i(TAG, "--onDestroy --Tools.isThemeChange:" + Tools.isThemeChange);

    mTvHandler.sendEmptyMessageDelayed(TV_MSG_RUN_STOP, 1);

        ...

    }

    

private void tuneTvView() {

        mTvInputId = null;

        mChannelUri = null;

        int device_id, index_atv, index_adtv;

        device_id = Settings.System.getInt(getContentResolver(), DroidLogicTvUtils.TV_CURRENT_DEVICE_ID, 0);

        index_adtv = Settings.System.getInt(getContentResolver(), DroidLogicTvUtils.TV_DTV_CHANNEL_INDEX, -1);

        isRadioChannel = Settings.System.getInt(getContentResolver(), DroidLogicTvUtils.TV_CURRENT_CHANNEL_IS_RADIO, 0) == 1 ? true : false;

        Log.d(TAG, "TV get device_id=" + device_id  +" adtv=" + index_adtv + " is_radio="+isRadioChannel);

        List<TvInputInfo> input_list = mTvInputManager.getTvInputList();

        for (TvInputInfo info : input_list) {

            if (parseDeviceId(info.getId()) == device_id) {

                mTvInputId = info.getId();

            }

        }

        mTvDataBaseManager = new TvDataBaseManager(this);

        if (TextUtils.isEmpty(mTvInputId)) {

            Log.d(TAG, "device" + device_id + " is not exist");

            return;

        } else {

            if (device_id == DroidLogicTvUtils.DEVICE_ID_ADTV) {

                ArrayList<ChannelInfo> channelList = mTvDataBaseManager.getChannelList(mTvInputId, TvContract.Channels.SERVICE_TYPE_AUDIO_VIDEO);

                Log.d(TAG, "channelList.size:" + channelList.size());

                if(index_adtv == -1){

                    mChannelUri = null;

                }else{

                    setChannelUri(channelList, index_adtv);

                }

            }else {

                mChannelUri = TvContract.buildChannelUriForPassthroughInput(mTvInputId);

            }

        }

        Log.d(TAG, "TV play tune inputId=" + mTvInputId + " uri=" + mChannelUri);

        if(mChannelUri != null){

          mTVNoDataBlockScreenView.setVisibility(View.GONE);

          mTVNoDataBlockScreenView.HideNoDataBaseTint();

          mTvView.tune(mTvInputId, mChannelUri);

        }else{

           Log.d(TAG, "show no database");

           TvControlManager mTvControlManager = TvControlManager.getInstance();

           int blueModeIndex = mTvControlManager.GetBlueScreenEnable();

           if(blueModeIndex==1)

              mTVNoDataBlockScreenView.setBackgroundResource(R.color.blue_screen);

           else

             mTVNoDataBlockScreenView.setBackgroundResource(R.color.black);

             mTVNoDataBlockScreenView.setVisibility(View.VISIBLE);

             mTVNoDataBlockScreenView.setNoDataBaseHint();

        }

    }

private final class TvInputChangeCallback extends TvInputManager.TvInputCallback {

        @Override

        public void onInputAdded(String inputId) {

            Log.d(TAG, "==== onInputAdded, inputId=" + inputId + " curent inputid=" + mTvInputId);

            int device_id = Settings.System.getInt(getContentResolver(), DroidLogicTvUtils.TV_CURRENT_DEVICE_ID, 0);

            if (device_id == parseDeviceId(inputId)) {

                switch (device_id) {

                    case DroidLogicTvUtils.DEVICE_ID_AV1:

                    case DroidLogicTvUtils.DEVICE_ID_AV2:

                    case DroidLogicTvUtils.DEVICE_ID_HDMI1:

                    case DroidLogicTvUtils.DEVICE_ID_HDMI2:

                    case DroidLogicTvUtils.DEVICE_ID_HDMI3:

                        mTvView.reset();

                        mTvInputId = inputId;

                        mChannelUri = TvContract.buildChannelUriForPassthroughInput(mTvInputId);

                        mTvView.tune(mTvInputId, mChannelUri);

                        break;

                }

            }

        }

 

        @Override

        public void onInputRemoved(String inputId) {

            Log.d(TAG, "==== onInputRemoved, inputId=" + inputId + " curent inputid=" + mTvInputId);

            if (TextUtils.equals(inputId, mTvInputId)) {

                Log.d(TAG, "==== current input device removed");

                mTvInputId = null;

            }

        }

    }

private int parseDeviceId(String inputId) {

        String[] temp = inputId.split("/");

        if (temp.length == 3) {

            /*  ignore for HDMI CEC device */

            if (temp[2].contains("HDMI"))

                return -1;

            return Integer.parseInt(temp[2].substring(2));

        } else {

            return -1;

        }

    }

    private void setChannelUri (ArrayList<ChannelInfo> channelList, int index) {

     Log.d(TAG, "===channelList.size() = "+channelList.size()+"   ,index = "+index);

        if (channelList.size() > 0) {

            if (index > 0) {

                for (ChannelInfo channelInfo : channelList) {

                    if (index == channelInfo.getNumber()) {

                        mChannelUri = channelInfo.getUri();

                        //setTvPrompt(TV_PROMPT_GOT_SIGNAL);

                        return;

                    }

                }

            }

            ChannelInfo channel = channelList.get(0);

            mChannelUri = channel.getUri();

            Settings.System.putInt(getContentResolver(), DroidLogicTvUtils.TV_ATV_CHANNEL_INDEX, 1);

            Settings.System.putInt(getContentResolver(), DroidLogicTvUtils.TV_CURRENT_CHANNEL_IS_RADIO,

                    ChannelInfo.isRadioChannel(channel) ? 1 : 0);

            //setTvPrompt(TV_PROMPT_GOT_SIGNAL);

        } else {

            mChannelUri = TvContract.buildChannelUri(-1);

        }

    }

    private final class ChannelObserver extends ContentObserver {

        public ChannelObserver() {

            super(new Handler());

        }

        @Override

        public void onChange(boolean selfChange, Uri uri) {

            Log.d(TAG, "detect channel changed =" + uri);

            if (DroidLogicTvUtils.matchsWhich(mChannelUri) == DroidLogicTvUtils.NO_MATCH) {

                ChannelInfo changedChannel = mTvDataBaseManager.getChannelInfo(uri);

                if (TextUtils.equals(changedChannel.getInputId(), mTvInputId)) {

                    Log.d(TAG, "current channel is null, so tune to a new channel");

                    mChannelUri = uri;

                    mTvView.tune(mTvInputId, mChannelUri);

                }

            }

        }

        @Override

        public IContentObserver releaseContentObserver() {

            // TODO Auto-generated method stub

            return super.releaseContentObserver();

        }

    }

private Handler mTvHandler = new Handler() {

        public void handleMessage(Message msg) {

            switch (msg.what) {

                case TV_MSG_PLAY_TV:

                    if (true) {

                        Log.d(TAG, "======== bootvideo is stopped, start tv play");

                        tuneTvView();

                        if(isFirst == true)

                        {

                         isFirst = false;

                            mTvHandler.sendEmptyMessageDelayed(TV_MSG_RUN_STOP, 500);

                        }

                    } else {

                        Log.d(TAG, "======== bootvideo is not stopped, wait it");

                        mTvHandler.sendEmptyMessageDelayed(TV_MSG_PLAY_TV, 200);

                    }

                    break;

                case TV_MSG_RUN_STOP:

                {

                 if (true) {

                        releaseTvView();

                        if (mTvInputChangeCallback != null) {

                            mTvInputManager.unregisterCallback(mTvInputChangeCallback);

                            mTvInputChangeCallback = null;

                        }

                        if (mChannelObserver != null) {

                            getContentResolver().unregisterContentObserver(mChannelObserver);

                            mChannelObserver = null;

                        }

                    }

                mTvHandler.sendEmptyMessageDelayed(TV_MSG_RUN_START, 500);

                }

                break;

                case TV_MSG_RUN_START:

                {

                 mTvView.setVisibility(View.VISIBLE);

                Log.d(TAG, "------onStart");

                    if (true) {

                        mTvInputManager = (TvInputManager) getSystemService(Context.TV_INPUT_SERVICE);

                        mTvInputChangeCallback = new TvInputChangeCallback();

                        mTvInputManager.registerCallback(mTvInputChangeCallback, new Handler());

                        mChannelObserver = new ChannelObserver();

                        getContentResolver().registerContentObserver(Channels.CONTENT_URI, true, mChannelObserver);

                        mTvView.setVisibility(View.VISIBLE);

                        mTvHandler.sendEmptyMessageDelayed(TV_MSG_PLAY_TV, 100);

                    }

                }

                break;

                default:

                    break;

            }

        }

};

...

}

 

注意AndroidManifest.xml中需要設置以下幾點:否則會出現無法讀寫TV 節目及設置當前通道的問題。

    android:sharedUserId="android.uid.system"

    <uses-permission android:name="android.permission.READ_TV_LISTINGS" />

 

三、後記

從使用上看來,關鍵部分是TvView,及TvView.tune(),其他類似TvInputChangeCallback此處沒意義。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章