Android Developer

เขียนแอพพลิเคชัน TV Online บน Android

บทเรียนนี้เราจะมาประยุกต์ใช้ Volley.jar ในการเก็บ Cache รูปภาพจากเว็บเซอร์วิสร่วมกับดึงข้อมูลรายการโทรทัศน์ หรือ Online TV ดูสดผ่านแอพพลิเคชันบนระบบปฏิบัติการ Android

สิ่งที่ต้องเรียนรู้ก่อนหน้าคือ

ถ้าหากว่าได้เรียนรู้มาหมดแล้ว และพร้อมแล้วก็มาเริ่มพัฒนาแอพพลิเคชันดูทีวีของเรากันดีกว่า

เริ่มต้นให้สร้าง New Project ขึ้นมาเป็น Basic Activity ตั้งชื่อตามใจชอบว่าเราจะให้แอพพลิเคชันของเราชื่ออะไรก็ตามใจครับ หลังจากนั้นให้เราไปดาวน์โหลด Volley.jar เป็น Library ในการจัดการ Resource จาก  Web Services ตัวเล็กๆ ตัวหนึ่งจากที่นี่ครับ (ผมอัพโหลดไว้ให้)

https://drive.google.com/file/d/0B08PZSOd4UmOTFBLbW1sQUlYVHc/view?usp=sharing

หรือหาตาม Google ก็ได้

เมื่อ Project ของเราบน Android Studio พร้อมแล้วให้เปิดโหมด Project View (ถ้าเป็น version 2.2 ก็จะอยู่ข้างๆ) เอา volley.jar ไปวางในโฟลเดอร์ libs ให้เรียบร้อยถ้าไม่มี ก็ออกไปที่ Windows Explorer เปิดไล่เอาครับ

Tv-Apps1

หลังจากวางตัว volley.jar ลงใน libs ของตัว Android Studio เป็นที่เรียบร้อยแล้วให้ทำการ แก้ไข Gradle ใหม่ โดยเพิ่มส่วนของ libs/volley.jar ลงไปแล้วทำการ Sync

Tv-Apps7

โดยแก้ไขเพิ่มเป็นตามนี้

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
    compile files('libs/volley.jar')
}

นั่นคือการเพิ่มส่วนของการเรียกใช้งาน volley.jar เข้าไป

compile files('libs/volley.jar')

หลังจากทำการ Sync Gradle เป็นที่เรียบร้อยแล้ว ให้ทำการสร้าง Package ขึ้นมาใน Project ของเราครับ โดยสร้าง Package เป็นส่วนที่ทำงานร่วมกับ Directory Structure ของตัว main/java เท่านั้นครับ

Tv-Apps3

Tv-Apps5

Package ที่เราจะสร้างนั้นประกอบไปด้วย adapter, controller, model, util

Tv-Apps2

แล้วทำการสร้าง Java Class File ตามรูปข้างบน นั่นคือ

  • สร้างไฟล์ AppController.java อยู่ใน Package “controller
  • สร้างไฟล์ LruBitmapCache.java ใน Package “util
  • สร้างไฟล์ TvModel.java ใน Package “model
  • สร้างไฟล์ CustomListAdapter.java ใน Package “adapter

เปิดไฟล์ LruBitmapCache.java ทำการ extends LruCache<String, Bitmap> implements ImageLoader.ImageCache ต่อท้ายแล้ว Implement Method ให้เรียบร้อย

ในตัวอย่างนี้ผมจะทำการปรับ CacheSize ไว้เป็นที่เรียบร้อยแล้ว

package util;

import android.graphics.Bitmap;
import android.util.LruCache;

import com.android.volley.toolbox.ImageLoader;

/**
 * Created by Banyapon on 6/26/2016.
 */
public class LruBitmapCache extends LruCache<String, Bitmap> implements ImageLoader.ImageCache {
    //TODO Create getDefaultCacheSize() method and setup cacheSize
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;
        return cacheSize;
    }

    public LruBitmapCache(){
        this(getDefaultLruCacheSize());
    }

    public LruBitmapCache(int maxSize) {
        super(maxSize);
    }
    //TODO insert protected sizeof()
    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String s) {
        return null;
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

ทำการเตรียม API ของส่วน JSON สำหรับดูทีวีให้เรียบร้อย ประกอบไปด้วย ชื่อช่อง ไฟล์รูปภาพช่องรายการ และ URL ของ M3u8 ที่เป็น Streaming Video ดูออนไลน์ โดยตัวอย่างนั้นจะประกอบไปด้วย Pattern JSON ตามนี้

[
 {
    _id: {
     $oid: "5712eff7e4b065a8c4d71825"
    },
    id: 3,
    title: "CH 3",
    detail: "URL File รูปภาพ",
    source: "URL Filee m3u8"
 },
 {
    _id: {
     $oid: "5712f072e4b065a8c4d7182b"
   },
   id: 5,
   title: "CH 5",
   detail: "URL File รูปภาพ",
   source: "URL Filee m3u8"
 }
]

แก้ไขไฟล์ TVModel.java ให้มีการเรียก Mapping Key Value ของ JSON ตามนี้

package model;

/**
 * Created by Banyapon on 6/26/2016.
 */
public class TVmodel {
    private String id,title,detail,source;

    public TVmodel(){

    }

    public TVmodel(String id, String title, String detail,String source){
        this.id = id;
        this.title = title;
        this.detail = detail;
        this.source = source;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }
}

เพื่อรับค่า String ทุกตัวใน JSON มาอยู่ในรูปแบบการทำงาน แบบ adapter,  controller และ model ต่อมาให้แก้ไขไฟล์ AppController.java โดยมีการเรียก Extend ตัว Application ทำการ Implement Method ให้เรียบร้อย ทำการเขียนคำสั่งในการ Load ไฟล์ Images ทั้งหมดเก็บใน Cache ผ่าน Class ของ LruBitmapCache

package controller;

import android.app.Application;
import android.text.TextUtils;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

import util.LruBitmapCache;

/**
 * Created by Banyapon on 6/26/2016.
 */
public class AppController extends Application {
    public static final String TAG = AppController.class.getSimpleName();
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static AppController mInstance;
    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
    }
    public static synchronized AppController getInstance() {
        return mInstance;
    }
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return mRequestQueue;
    }
    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (mImageLoader == null) {
            mImageLoader = new ImageLoader(this.mRequestQueue,
                    new LruBitmapCache());
        }
        return this.mImageLoader;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

    public <T> void addToRequestQueue(Request<T> req) {
        req.setTag(TAG);
        getRequestQueue().add(req);
    }

    public void cancelPendingRequests(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        }
    }
}

ให้ทำการเพิ่ม Layout ใหม่ขึ้นมาชื่อว่า grid_layout.xml ใส่รูปแบบต่อไปนี้

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/thumbnail"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:gravity="center"
        android:textSize="14sp"
        android:textStyle="bold"
        android:textColor="#000000" />
</LinearLayout>

เป็นการเก็บส่วนของ component widget ภายใน Grid View เพื่อแสดงรูปภาพ และชื่อช่อง ดังนั้นต้องไปแก้ไขไฟล์ content_main.xml อีกทีโดยการเพิ่ม gridView เข้าไป

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.daydev.tutorialtv.MainActivity"
    tools:showIn="@layout/activity_main">
    <GridView
        android:id="@+id/gridView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:columnWidth="100dp"
        android:drawSelectorOnTop="true"
        android:gravity="center"
        android:numColumns="auto_fit"
        android:stretchMode="columnWidth"
        android:verticalSpacing="5dp"
        android:focusable="true"
        android:clickable="true"
        android:background="#ffffff" />
</RelativeLayout>

หมายเหตุ: ในตัวอย่างผมตัดส่วนของ Fab Button ออกจากตัวอย่างไปเป็นที่เรียบร้อยจาก activity_main.xml

แก้ไขไฟล์ CustomListAdapter.java เพิ่มส่วนของการ ดึงข้อมูลจาก TVmodel แต่ละ Key ไปผูกค่ากับ id แต่ละตัวของ grid_layout.xml

package adapter;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;
import com.daydev.tutorialtv.R;

import java.util.List;

import controller.AppController;
import model.TVmodel;

/**
 * Created by Banyapon on 6/26/2016.
 */
public class CustomListAdapter extends BaseAdapter {
    private Activity activity;
    private LayoutInflater inflater;
    private List<TVmodel> dataItems;
    ImageLoader imageLoader = AppController.getInstance().getImageLoader();
    public CustomListAdapter(Activity activity, List<TVmodel> dataItems) {
        this.activity = activity;
        this.dataItems = dataItems;
    }
    @Override
    public int getCount() {
        return dataItems.size();
    }

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (inflater == null)
            inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null)
            convertView = inflater.inflate(R.layout.grid_layout, null);
        if (imageLoader == null)
            imageLoader = AppController.getInstance().getImageLoader();
        NetworkImageView thumbNail = (NetworkImageView) convertView
                .findViewById(R.id.thumbnail);
        TextView title = (TextView) convertView.findViewById(R.id.text);

        // getting movie data for the row
        TVmodel m = dataItems.get(position);
        // thumbnail image
        thumbNail.setImageUrl(m.getDetail(), imageLoader);
        // title
        title.setText(m.getTitle());

        return convertView;
    }
}

เราจะสามารถผูกค่า Key ทั้งหลายที่รับมาจาก JSON มาลงที่ Activity ได้แล้วทีนี้ก็เหลือแค่การดึงข้อมูลจาก URL ของ API ไปปรากฏบน Gridview เปิดไฟล์ MainActivity.java ขึ้นมาเขียนคำสั่งลงไป

package com.daydev.tutorialtv;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.GridView;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import adapter.CustomListAdapter;
import controller.AppController;
import model.TVmodel;

public class MainActivity extends AppCompatActivity {
    // Log tag
    private static final String TAG = MainActivity.class.getSimpleName();

    // Movies json url
    private static final String url = "<<ใส่ URL ของ API>>";
    private ProgressDialog pDialog;
    private List<TVmodel> dataList = new ArrayList<TVmodel>();
    private GridView gridView;
    private CustomListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        gridView = (GridView) findViewById(R.id.gridView);
        adapter = new CustomListAdapter(this, dataList);
        gridView.setAdapter(adapter);

        pDialog = new ProgressDialog(this);

        pDialog.setMessage("Loading Data...");
        pDialog.show();

        JsonArrayRequest movieReq = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, response.toString()); hidePDialog();
                        for (int i = 0; i < response.length(); i++) {                    
                            try {
                                JSONObject obj = response.getJSONObject(i);
                                TVmodel movie = new TVmodel();
                                movie.setTitle(obj.getString("title"));
                                movie.setDetail(obj.getString("detail"));
                                movie.setSource(obj.getString("source"));
                                dataList.add(movie);

                            } catch (JSONException e) {e.printStackTrace(); }
                        }
                        adapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                hidePDialog();
            }
        });
        AppController.getInstance().addToRequestQueue(movieReq);
    }

    private void hidePDialog() {
        if (pDialog != null) {
            pDialog.dismiss();
            pDialog = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        hidePDialog();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

ค่าในการรับค่า JSON นั้นอยู่ที่คำสั่ง ปรกติคือ getJSONObject();

JsonArrayRequest movieReq = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, response.toString()); hidePDialog();
                        for (int i = 0; i < response.length(); i++) {                    
                            try {
                                JSONObject obj = response.getJSONObject(i);
                                TVmodel movie = new TVmodel();
                                movie.setTitle(obj.getString("title"));
                                movie.setDetail(obj.getString("detail"));
                                movie.setSource(obj.getString("source"));
                                dataList.add(movie);

                            } catch (JSONException e) {e.printStackTrace(); }
                        }
                        adapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                hidePDialog();
            }
        });
        AppController.getInstance().addToRequestQueue(movieReq);

ต่อมาให้สร้าง Activity อีกตัวชื่อว่า MainAcctivity2.java ใหม่เพิ่มเข้าไปเพื่อสร้างหน้าดูทีวีออนไลน์

Tv-Apps6

โดยทำการเพิ่มส่วนของ Intent กดเพื่อส่งค่า source และ param อื่นๆ จาก MainActivity.java ไปยัง MainActivity2.java ตามนี้

gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        int itemPosition = position;
        Intent showPage = new Intent(MainActivity.this,MainActivity2.class);
        showPage.putExtra("title",""+dataList.get(position).getTitle()+"");
        showPage.putExtra("source",""+dataList.get(position).getSource()+"");
        startActivity(showPage);

    }
});

คำสั่งหน้า MainActivity.java จะเป็นดังนี้

package com.daydev.tutorialtv;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AdapterView;
import android.widget.GridView;

import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonArrayRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import adapter.CustomListAdapter;
import controller.AppController;
import model.TVmodel;

public class MainActivity extends AppCompatActivity {
    // Log tag
    private static final String TAG = MainActivity.class.getSimpleName();

    // Movies json url
    private static final String url = "<<URL ของ API>>";
    private ProgressDialog pDialog;
    private List<TVmodel> dataList = new ArrayList<TVmodel>();
    private GridView gridView;
    private CustomListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        gridView = (GridView) findViewById(R.id.gridView);
        adapter = new CustomListAdapter(this, dataList);
        gridView.setAdapter(adapter);

        pDialog = new ProgressDialog(this);
        // Showing progress dialog before making http request
        pDialog.setMessage("Loading Data...");
        pDialog.show();

        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                int itemPosition = position;
                Intent showPage = new Intent(MainActivity.this,MainActivity2.class);
                showPage.putExtra("title",""+dataList.get(position).getTitle()+"");
                showPage.putExtra("source",""+dataList.get(position).getSource()+"");
                startActivity(showPage);

            }
        });

        JsonArrayRequest movieReq = new JsonArrayRequest(url,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, response.toString()); hidePDialog();
                        for (int i = 0; i < response.length(); i++) {                    // Parsing json
                            try {
                                JSONObject obj = response.getJSONObject(i);
                                TVmodel movie = new TVmodel();
                                movie.setTitle(obj.getString("title"));
                                movie.setDetail(obj.getString("detail"));
                                movie.setSource(obj.getString("source"));

                                dataList.add(movie);

                            } catch (JSONException e) {e.printStackTrace(); }
                        }
                        adapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                hidePDialog();
            }
        });
        AppController.getInstance().addToRequestQueue(movieReq);

    }

    private void hidePDialog() {
        if (pDialog != null) {
            pDialog.dismiss();
            pDialog = null;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        hidePDialog();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

เปิดไฟล์ MainActivity2.java ขึ้นมาเขียนคำสั่งในการรับค่าจาก Intent มาแสดงข้อมูลผ่าน VideoView ดังนั้นต้องไปแก้ไขไฟล์ content_main2.xml ก่อนดังนี้

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.daydev.tutorialtv.MainActivity2"
    tools:showIn="@layout/activity_main2">
    <VideoView
        android:id="@+id/VideoPlayer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />
</RelativeLayout>

แล้วแก้ไข MainActivity2.java ดังนี้

package com.daydev.tutorialtv;

import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.MediaController;
import android.widget.VideoView;

import java.net.URL;

public class MainActivity2 extends AppCompatActivity {
    private String urlStream;
    private VideoView myVideoView;
    private URL url;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Intent intent= getIntent();
        setTitle(intent.getStringExtra("title"));


        VideoView videoView = (VideoView) findViewById(R.id.VideoPlayer);
        String httpLiveUrl = intent.getStringExtra("source");
        videoView.setVideoURI(Uri.parse(httpLiveUrl));
        videoView.setMediaController(new MediaController(this));
        videoView.requestFocus();
        videoView.start();
    }

    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            getActionBar().hide();
        } else {
            getActionBar().hide();
        }
    }

}

ขั้นตอนสุดท้ายแล้วคือเปิด Permission และแก้ไข android:name เล็กน้อย นั่นคือบรรทัดต่อไปนี้ใน AndroidManifest.xml

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

และ

android:name="controller.AppController"

ไฟล์ AndroidManifest.xml จะเป็นดังนี้ เปิดเทียบดูนะครับ

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.daydev.tutorialtv">

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

    <application
        android:name="controller.AppController"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar"
            android:configChanges="orientation|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".MainActivity2"
            android:label="@string/title_activity_main2"
            android:theme="@style/AppTheme.NoActionBar"></activity>
    </application>

</manifest>

ตกแต่งความสวยงานของ res/values/color.xml ตามนี้

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#49e15d</color>
    <color name="colorPrimaryDark">#059e02</color>
    <color name="colorAccent">#fd8b00</color>
    <color name="backgroundBlack">#000</color>
</resources>

ทดสอบแอพพลิเคชันของเราหน่อยดีกว่า เสียบ USB เปิด USB Debugging แล้ว Run ตัวแอพพลิเคชันไปเลย

Android Live TV
แนวตั้ง

Screenshot_2016-06-26-13-53-56-34

ลองปรับแนวนอนดู

Screenshot_2016-06-26-13-54-53-67

Screenshot_2016-06-26-13-54-30-62

ก็แปลว่าใช้ได้แล้ว เอาไปประยุคใช้หากินกันต่อไปแล้วกันนะครับ ทุกคน แนะนำว่าอย่าทำ ฟรีทีวีเลยแต่ทำเป็นช่องทีวีของตัวเองก็ยังดีกว่านะครับ ไปลงทุนส่วนของ Server ก็ไม่มีปัญหาแล้ว

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน