智能电视TV开发---直播视频客户端结构设计和实现

智能电视TV开发---客户端和服务器通信里面我们实现了客户端和服务端的简单通信,接下来我们做一个简单的客户端界面,来实现手机端来操控智能电视的TV端。

一、存储视频的结构设计

我们在做客户端的时候,通常是需要存储视频的相关信息,结构如下:

 

package com.jwzhangjie.smarttv_client.model;

import android.os.Parcel;
import android.os.Parcelable;

public class LiveModel implements Parcelable{
	
	/**
	 * 数据库位置
	 */
	private int db_id;
	/**
	 * 直播频道的id
	 */
	private int channel_id;
	/**
	 * 直播频道的名称
	 */
	private String channel_name;
	/**
	 * 直播频道的url
	 */
	private String icon_url;
	/**
	 * 直播频道的省份
	 */
	private String province;
	/**
	 * 直播频道清晰度
	 */
	private String mode;
	/**
	 * 直播频道的链接
	 */
	private String url;
	/**
	 * 直播频道的second_url
	 */
	private String second_url;
	/**
	 * 直播频道所属的类型
	 */
	private String types;
	

	public LiveModel(){
		
	}
	private LiveModel(Parcel parcel){
		readFromParcel(parcel);
	}
	@Override
	public int describeContents() {
		return 0;
	}

	public void readFromParcel(Parcel parcel){
		db_id = parcel.readInt();
		channel_id = parcel.readInt();
		channel_name = parcel.readString();
		icon_url = parcel.readString();
		province = parcel.readString();
		mode = parcel.readString();
		url  = parcel.readString();
		second_url = parcel.readString();
		types = parcel.readString();
	}
	@Override
	public void writeToParcel(Parcel dest, int flags) {
		dest.writeInt(db_id);
		dest.writeInt(channel_id);
		dest.writeString(channel_name);
		dest.writeString(icon_url);
		dest.writeString(province);
		dest.writeString(mode);
		dest.writeString(url);
		dest.writeString(second_url);
		dest.writeString(types);
	}
	
	public static Creator<LiveModel> CREATOR = new Creator<LiveModel>() {

		@Override
		public LiveModel createFromParcel(Parcel source) {
			return new LiveModel(source);
		}

		@Override
		public LiveModel[] newArray(int size) {
			return new LiveModel[size];
		}
	};

	public int getDb_id() {
		return db_id;
	}
	public void setDb_id(int db_id) {
		this.db_id = db_id;
	}
	public int getChannel_id() {
		return channel_id;
	}
	public void setChannel_id(int channel_id) {
		this.channel_id = channel_id;
	}
	public String getChannel_name() {
		return channel_name;
	}
	public void setChannel_name(String channel_name) {
		this.channel_name = channel_name;
	}
	public String getIcon_url() {
		return icon_url;
	}
	public void setIcon_url(String icon_url) {
		this.icon_url = icon_url;
	}
	public String getProvince() {
		return province;
	}
	public void setProvince(String province) {
		this.province = province;
	}
	public String getMode() {
		return mode;
	}
	public void setMode(String mode) {
		this.mode = mode;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	public String getSecond_url() {
		return second_url;
	}
	public void setSecond_url(String second_url) {
		this.second_url = second_url;
	}
	public String getTypes() {
		return types;
	}
	public void setTypes(String types) {
		this.types = types;
	}
	
}

 

 

二、数据库设计

  接下来我们设计数据库表格,代码如下:
  
package com.jwzhangjie.smarttv_client.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;

public class DBHelper extends SQLiteOpenHelper{

	private static final String NAME = "tv_jie.sqlite";
	public static final String DB_PATH = Environment.getExternalStorageDirectory() + "/";
	private static final int DB_VERSION = 1;
	public static final String LIVE_VIDEO="CREATE TABLE live_video " +
			"('db_id' INTEGER PRIMARY KEY  AUTOINCREMENT, 'channel_id' INTEGER," +
			" 'channel_name' VARCHAR, 'icon_url' VARCHAR, 'province' VARCHAR, 'mode' VARCHAR, " +
			"'url' VARCHAR, 'second_url' VARCHAR, 'types' VARCHAR)";
	
	public DBHelper(Context context) {
		super(context, DB_PATH + NAME, null, DB_VERSION);
	}

	public DBHelper(Context context, String name, CursorFactory factory,
			int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(LIVE_VIDEO);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("DROP TABLE IF live_video");
	}
	
}

三、调用数据库,首先数据的插入,或直播,获取直播的个数

package com.jwzhangjie.smarttv_client.utils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.jwzhangjie.smarttv_client.db.DBHelper;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DBUtils implements Serializable{

	private static final long serialVersionUID = 1L;

	private static DBHelper mDBHelper;
	
	public DBUtils(Context paramContext) {
		mDBHelper = new DBHelper(paramContext);
	}

	public void close() {
		if (mDBHelper != null) {
			mDBHelper.close();
		}
	}
	
	public void insertLiveVideo(LiveVideoModel liveModel){
		SQLiteDatabase db = null;
		try {
			db = mDBHelper.getWritableDatabase();
			ContentValues contentValues = new ContentValues();
			contentValues.put("channel_id", liveModel.getChannel_id());
			contentValues.put("channel_name", liveModel.getChannel_name());
			contentValues.put("icon_url", liveModel.getIcon_url());
			contentValues.put("province", liveModel.getProvince());
			contentValues.put("mode", liveModel.getMode());
			contentValues.put("url", liveModel.getUrl());
			contentValues.put("second_url", liveModel.getSecond_url());
			contentValues.put("types", liveModel.getTypes());
			db.insertOrThrow("live_video", null, contentValues);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取所有的直播视频的个数
	 * @return
	 */
	public int getMovieCount() {
		SQLiteDatabase db = mDBHelper.getReadableDatabase();
		Cursor cursor = db.rawQuery("SELECT count(*) FROM live_video", null);
		cursor.moveToNext();
		int coutn = cursor.getInt(0);
		cursor.close();
		db.close();
		return coutn;
	}
	
	public List<LiveVideoModel> getLiveVideoModels(){
		List<LiveVideoModel> listData = new ArrayList<LiveVideoModel>();
		try {
			SQLiteDatabase db = mDBHelper.getReadableDatabase();
			Cursor cursor = db.rawQuery("SELECT * FROM live_video", null);
			while (cursor.moveToNext()) {
				LiveVideoModel mVideoModel = new LiveVideoModel();
				mVideoModel.setDb_id(cursor.getInt(0));
				mVideoModel.setChannel_id(cursor.getInt(1));
				mVideoModel.setChannel_name(cursor.getString(2));
				mVideoModel.setIcon_url(cursor.getString(3));
				mVideoModel.setProvince(cursor.getString(4));
				mVideoModel.setMode(cursor.getString(5));
				mVideoModel.setUrl(cursor.getString(6));
				mVideoModel.setSecond_url(cursor.getString(7));
				mVideoModel.setTypes(cursor.getString(8));
				listData.add(mVideoModel);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return listData;
	}
	
}
具体的数据自己去填充,这里我就不提供了,各大视频论坛都分享

四、客户端视频数据的显示

  这里已经假设数据库已经有数据了,界面很简单就是一个listView来显示,自定义一个adapter

4.1ListView中Item的设计

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >
    <ImageView
        android:id="@+id/item_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:layout_centerVertical="true"
        android:src="@drawable/widget_progress_medium_rotation_image"
        android:contentDescription="@string/app_name"
        />
    <ImageView
	    android:id="@+id/arrow_right"
	    android:layout_width="wrap_content"
	    android:layout_height="wrap_content"
	    android:src="@drawable/arrow_right"
	    android:layout_alignParentRight="true"
	    android:layout_centerVertical="true"
	    android:layout_marginRight="10dip"
	    android:contentDescription="@string/app_name"
	    />
	<LinearLayout 
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:layout_toRightOf="@id/item_icon"
	    android:layout_toLeftOf="@id/arrow_right"
	    android:orientation="vertical"
	    android:gravity="center_vertical"
	    android:layout_centerVertical="true"
	    android:layout_marginLeft="10dip"
	    >
	    <TextView 
	        android:id="@+id/item_title"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="title"
	        />
	    <TextView 
	        android:id="@+id/item_subtitle"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="subtitle"
	        />
	</LinearLayout>
</RelativeLayout>

4.2网络图片加载方式

这里涉及的直播频道的图标都是网络图片,所以要实现加载网络图片的功能,这里我使用的是网络一个开源的库com.nostra13.universalimageloader,在网上一搜就能看见,所以要使用它我们要配置一些内容。
首先编写一个类继承Application,然后再AndroidManifest.xml里面设置Application的name属性,代码如下:
package com.jwzhangjie.smarttv_client.utils;

import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;

import android.app.Application;
import android.content.Context;

public class SmartTV_App extends Application {

	@Override
	public void onCreate() {
		super.onCreate();
		initImageLoader(getApplicationContext());
	}

	public static void initImageLoader(Context context) {
		ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
				context).threadPriority(Thread.NORM_PRIORITY - 2)
				.denyCacheImageMultipleSizesInMemory()
				.discCacheFileNameGenerator(new Md5FileNameGenerator())
				.tasksProcessingOrder(QueueProcessingType.LIFO)
				.writeDebugLogs() // Remove for release app
				.build();
		ImageLoader.getInstance().init(config);
	}
}

4.3ListView的adapter设计

package com.jwzhangjie.smarttv_client.adapter;

import java.util.List;

import com.jwzhangjie.smarttv_client.R;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class LiveVideoAdapter extends BaseAdapter{
	
	private LayoutInflater mInflater;
	private List<LiveVideoModel> listDatas;
	private ImageLoader imageLoader = ImageLoader.getInstance();
	private DisplayImageOptions options;
	public LiveVideoAdapter(Context context){
		mInflater = LayoutInflater.from(context);
		options = new DisplayImageOptions.Builder()
			.showImageOnLoading(R.drawable.img_loading_bg)
			.showImageForEmptyUri(R.drawable.img_loading_empty)
			.showImageOnFail(R.drawable.img_loading_error)
			.cacheInMemory(true)
			.cacheOnDisc(true)
			.bitmapConfig(Bitmap.Config.RGB_565)
			.build();
	}
	
	public void updateListDatas(List<LiveVideoModel> listDatas){
		this.listDatas = listDatas;
		notifyDataSetChanged();
	}
	@Override
	public int getCount() {
		return listDatas == null ?0:listDatas.size();
	}

	@Override
	public Object getItem(int position) {
		return listDatas.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder viewHolder;
		if (convertView == null) {
			viewHolder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.item_live, null);
			viewHolder.item_icon = (ImageView)convertView.findViewById(R.id.item_icon);
			viewHolder.item_arrow = (ImageView)convertView.findViewById(R.id.arrow_right);
			viewHolder.item_title = (TextView)convertView.findViewById(R.id.item_title);
			viewHolder.item_subtitle = (TextView)convertView.findViewById(R.id.item_subtitle);
			convertView.setTag(viewHolder);
		}else {
			viewHolder = (ViewHolder)convertView.getTag();
		}
		LiveVideoModel videoModel = listDatas.get(position);
		viewHolder.item_title.setText(videoModel.getChannel_name());
		viewHolder.item_subtitle.setText("省份:"+videoModel.getProvince());
		imageLoader.displayImage(videoModel.getIcon_url(), viewHolder.item_icon, options);
		return convertView;
	}
	
	class ViewHolder{
		private ImageView item_icon;
		private ImageView item_arrow;
		private TextView item_title;
		private TextView item_subtitle;
	}

}

4.4主界面布局设计

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Smart_TV_Client" >

    <RelativeLayout
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="60dip"
        android:background="#d0d0d0"
        >
        <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="直播界面测试"
            android:layout_centerInParent="true"
            android:textSize="16sp"
            android:textStyle="bold"
            />
    </RelativeLayout>
	<ListView 
	    android:id="@+id/listview"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
	    android:layout_below="@id/title"
        android:cacheColorHint="#00000000"
        android:divider="@drawable/cbox_uc_divider"
        android:fadeScrollbars="false"
        android:fastScrollEnabled="false"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:scrollbars="none"
        android:scrollingCache="false"
	    ></ListView>
</RelativeLayout>

4.5 主界面代码编写

这里就是这章最后的一步,调用数据库数据,然后传值给adapter,显示在listview上面
package com.jwzhangjie.smarttv_client;

import java.util.List;

import com.jwzhangjie.smarttv_client.adapter.LiveVideoAdapter;
import com.jwzhangjie.smarttv_client.model.LiveVideoModel;
import com.jwzhangjie.smarttv_client.utils.DBUtils;

import android.os.AsyncTask;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.Window;
import android.widget.ListView;

public class Smart_TV_Client extends Activity {

	private ListView listView;
	private LiveVideoAdapter adapter;
	private DBUtils dbUtils;
	private List<LiveVideoModel> listDatas;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_smart__tv__client);
		dbUtils = new DBUtils(this);
		initView();
		loadData();
	}
	
	public void initView(){
		adapter = new LiveVideoAdapter(this);
		listView = (ListView)findViewById(R.id.listview);
		listView.setAdapter(adapter);
	}
	
	public void loadData(){
		new loadData().execute();
	}
	
	private class loadData extends AsyncTask<Void, Void, Void>{
		@Override
		protected Void doInBackground(Void... params) {
			listDatas = dbUtils.getLiveVideoModels();
			return null;
		}

		@Override
		protected void onPostExecute(Void result) {
			adapter.updateListDatas(listDatas);
			super.onPostExecute(result);
		}
		
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.smart__tv__client, menu);
		return true;
	}

}

5.显示效果




 

 

 

posted on 2013-12-20 11:18  love so much  阅读(951)  评论(0编辑  收藏  举报

导航