zoukankan      html  css  js  c++  java
  • 智能电视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.显示效果




  • 相关阅读:
    JavaScript 浮点数处理
    从输入URL到浏览器显示页面发生了什么
    hadoop 编译任意版本的eclipse 插件
    Stm32F103面向对象编程之GPIO
    flume 1.7 安装与使用
    HIVE分组排序问题
    MapReduce实现共同朋友问题
    hadoop项目实战--ETL--(三)实现mysql表到HIVE表的全量导入与增量导入
    hadoop项目实战--ETL--(二)实现自动向mysql中添加数据
    hadoop项目实战--ETL--(一)项目分析
  • 原文地址:https://www.cnblogs.com/riasky/p/3483500.html
Copyright © 2011-2022 走看看