[Open-Source project] TVRemoteIME interface for control applications of Smart TVs and TV boxes,

Source: Internet
Author: User

[Open-Source project] TVRemoteIME interface for control applications of Smart TVs and TV boxes,
1. APP project introduction:

APP name:TVRemoteIME

Function Description:Android smart TV or android box control applications can be remotely input and remotely controlled across screens (instead of Remote Control) box, box application and file management, HTTP/RTMP/MMS network live video, ED2K/seed file video file playback

Project address:Https://github.com/kingthy/TVRemoteIME

APK package download:Https://github.com/kingthy/TVRemoteIME/raw/master/released/IMEService-release.apk

 

2. APP console interface

The control end does not need to install any APK application. It can be accessed directly by a mobile phone, computer, or PAD browser on the same LAN.

Input remote control:

Application Management:

 

 

File Management:

 

 

Livevideo:

 

 

Iii. APP core functions

1. IMEService:The main core portal of the APP, inherited from InputMethodService, is used to implement the input service and provides a simple QWERT keyboard UI. The core remote control function is also implemented through this service.

2. RemoteServer:The Web API service of the APP implements the Web service through NanoHTTPD. All operations on the control end are directly implemented by calling the WebAPI interface of the service.

3. ijkplayer project:The Video Player project is implemented by encapsulating the ijkplayer. It is closed for parsing and downloading the video source. It supports live video broadcast over HTTP/RTMP/MMS and live video files under ED2K/seed files.

4. thunder project:Third-party download service for downloading video sources

5366index.html and ime_core.js:Implement the functional page and script code of the control end. All operations on the control end are implemented through this page and script.

 

Iv. Introduction to WebAPI

1. "/text": Text input interface for cross-screen input

Code File: InputRequestProcesser. java

Parameters:

Text = the text to be input. It can contain any number of characters.

Call example:

POST/texttext = text to be input

Code implementation:

After receiving an Interface request, the Web Service notifies the input method service IMEService through the onTextReceived event Method of DataReceiver. The input method submits the remotely entered text to the corresponding input box through the commitText method.

    private boolean commitText(String text){        InputConnection ic = getCurrentInputConnection();        boolean flag = false;        if (ic != null){            Log.d(TAG, "commitText:" + text);            if(text.length() > 1 && ic.beginBatchEdit()){                flag = ic.commitText(text, 1);                ic.endBatchEdit();            }else{                flag = ic.commitText(text, 1);            }        }        return flag;    }

 

2. "/key", "/keydown", "/keyup":The three interfaces enable different input states of the buttons: "Press", "press", "Pop Up". It can be used for key operations, such as remote control.

Code File: InputRequestProcesser. java

Parameters:

Code = key code, which corresponds to the key code defined in the android KeyEvent. The key code "cls" defined in the special definition indicates that the text is cleared.

Call example:

POST /keycode=cls

 

POST /keydowncode=67

Code implementation:

After receiving the Interface request, the Web Service notifies the input method service IMEService through the onKeyEventReceived event Method of DataReceiver. The input method service then processes the request based on the key code and key actions.

                @Override                public void onKeyEventReceived(String keyCode, int keyAction) {                    if(keyCode != null) {                        if("cls".equalsIgnoreCase(keyCode)){                            InputConnection ic = getCurrentInputConnection();                            if(ic != null) {                                ic.performContextMenuAction(android.R.id.selectAll);                                ic.commitText("", 1);                            }                        }else {                            final int kc = KeyEvent.keyCodeFromString(keyCode);                            if(kc != KeyEvent.KEYCODE_UNKNOWN){                                if(mInputView != null && KeyEventUtils.isKeyboardFocusEvent(kc) && mInputView.isShown()){                                    if(keyAction == KEY_ACTION_PRESSED || keyAction == KEY_ACTION_DOWN) {                                        handler.post(new Runnable() {                                            @Override                                            public void run() {                                                if (!handleKeyboardFocusEvent(kc)) {                                                    sendKeyCode(kc);                                                }                                            }                                        });                                    }                                }                                else{                                    long eventTime = SystemClock.uptimeMillis();                                    InputConnection ic = getCurrentInputConnection();                                    switch (keyAction) {                                        case KEY_ACTION_PRESSED:                                            sendKeyCode(kc);                                            break;                                        case KEY_ACTION_DOWN:                                            if(ic != null) {                                                ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,                                                        KeyEvent.ACTION_DOWN, kc, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,                                                        KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));                                            }                                            break;                                        case KEY_ACTION_UP:                                            if(ic != null) {                                                ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,                                                    KeyEvent.ACTION_UP, kc, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,                                                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));                                            }                                            break;                                    }                                }                            }                        }                    }                }

 

3. "/apps ":Obtains the list of APP data installed on the box to manage the box APP.

Code File: AppRequestProcesser. java

Parameters:

System = system application included, true or false

Call example:

POST /appssystem=false

Code implementation:

You can use PackageManager to query the list of apps installed on the box and filter out the apps (not third-party) at the bottom of the system while processing the list data ).

Public static List <AppInfo> queryAppInfo (Context context, boolean containSysApp) {PackageManager pm = context. getPackageManager (); List <ApplicationInfo> listAppcations = pm. getInstalledApplications (PackageManager. MATCH_UNINSTALLED_PACKAGES); List <AppInfo> appInfos = new ArrayList <AppInfo> (); for (ApplicationInfo app: listAppcations) {if (containSysApp | (app. flags & ApplicationInfo. FLAG_SYSTEM) = 0) {boolean isSysApp = (app. flags & ApplicationInfo. FLAG_SYSTEM )! = 0; // filter out the app if (isSysApp & (app. packageName. startsWith ("com. android. ") | app. packageName. equals ("android") continue; AppInfo appInfo = new AppInfo (); appInfo. setLable (String) app. loadLabel (pm); appInfo. setPackageName (app. packageName); appInfo. setApkPath (app. sourceDir); appInfo. setSysApp (isSysApp); appInfos. add (appInfo) ;}} Collections. sort (appInfos, new Comparator <AppInfo> () {@ Override Public int compare (AppInfo o1, AppInfo o2) {int i1 = (o1.isSysApp? 2: 1); int i2 = (o2.isSysApp? 2: 1); if (i1 = i2) {return o1.getLable (). compareTo (o2.getLable ();} else {return Integer. compare (i1, i2) ;}}); return appInfos ;}

 

4. "/uninstall ":Uninstall application interface

Code File: AppRequestProcesser. java

Parameters:

PackageName = Name of the uninstalled application package

Call example:

POST /uninstallpackageName=com.test.app

Code implementation:

Directly call the system to uninstall the service.

Public static void uninstallPackage (final String packageName, final Context context) {if (getApplicationInfo (packageName, context) = null) return; try {Intent intent = new Intent (); intent. addFlags (Intent. FLAG_ACTIVITY_NEW_TASK); intent. setAction (Intent. ACTION_DELETE); intent. setData (Uri. parse ("package:" + packageName); context. startActivity (intent); Log. I (IMEService. TAG, String. format ("deleted application package [% s]", packageName);} catch (Exception ex) {Log. e (IMEService. TAG, String. format ("failed to delete application package [% s]", packageName), ex );}}

 

5. "/run", "/runSystem ":Run the application and or call the system application service. For example, the system settings page is displayed.

Code File: AppRequestProcesser. java

Parameters:

PackageName = Name of the application package to run

Call example:

POST /runpackageName=com.test.app

 

POST /runSystempackageName=android.settings.SETTINGS

Code implementation:

To run a third-party application, you can use PackageManager to obtain the startup page of the package and then run the application. To call the system application service, you can use Intent to directly start the application.

Public static void runPackage (final String packageName, final Context context) {if (getApplicationInfo (packageName, context) = null) return; try {PackageManager pm = context. getPackageManager (); Intent intent = pm. getLaunchIntentForPackage (packageName); if (intent! = Null) {context. startActivity (intent);} Log. I (IMEService. TAG, String. format ("running application package [% s]", packageName);} catch (Exception ex) {Log. e (IMEService. TAG, String. format ("error in running application package [% s]", packageName), ex) ;}} public static void runSystemPackage (final String packageName, final Context context) {try {Intent intent = new Intent (packageName); intent. addFlags (Intent. FLAG_ACTIVITY_NEW_TASK); context. startActivity (intent); Log. I (IMEService. TAG, String. format ("Running System Application Package [% s]", packageName);} catch (Exception ex) {Log. e (IMEService. TAG, String. format ("error in running system application package [% s]", packageName), ex );}}

 

6. "/upload ":File Transfer interface. The file transfer interface under the "input Remote Control" interface. If the APK package is transferred, it can be automatically installed. If it is a video file or a seed file, it can be automatically played.

Code File: UploadRequestProcesser. java

Parameters:

File = uploaded file

AutoPlay = whether to automatically install the APK package or play videos and seed files automatically, true or false

Call example:

POST /upload-------

Code implementation:

The file upload function of NanoHTTPD is used directly. To avoid moving files across "partitions", NanoHTTPD's TempFileManager is rewritten so that files can be uploaded directly to the files directory under the IMEService data directory.

For the code, see the RemoteServerFileManager. java file.

 

7. "/play ":Video Playback Service Interface

Code File: PlayRequestProcesser. java

Parameters:

PlayUrl = Source Address of the video to be played

Call example:

POST /playplayUrl=http://www.test.com/test.avi

Code implementation:

Directly transfer the video source address to the player of the ijkplayer project for playback.

XLVideoPlayActivity.intentTo(context, url, url);

 

8. "/file/dir /":The file management interface service enables you to view files and directories in a box.

Code File: FileRequestProcesser. java

Parameters:

None

Call example:

GET/file/dir/{view file or directory path}

Code implementation:

Obtains the list of subdirectories and files in the directory and returns JSON data.

   private NanoHTTPD.Response responseDirData(String dirName) {        File path = new File(Environment.getExternalStorageDirectory(), dirName);        String root = Environment.getExternalStorageDirectory().getPath();        JSONArray dirs = new JSONArray();        JSONArray files = new JSONArray();        try {            File[] subfiles = path.listFiles();            Arrays.sort(subfiles, new Comparator<File>() {                @Override                public int compare(File f1, File f2) {                    return f1.getName().toLowerCase().compareTo(f2.getName().toLowerCase());                }            });            for (File file : subfiles) {                if(file.isHidden()) continue;                JSONObject item = new JSONObject();                item.put("name", file.getName());                item.put("path", file.getPath().substring(root.length()));                if (file.isDirectory()) {                    //item.put("total", 0);                    dirs.put(item);                }else {                    item.put("size", file.length());                    files.put(item);                }            }            JSONObject data = new JSONObject();            if(!TextUtils.isEmpty(dirName) && dirName != "/") data.put("parent", path.getParent().substring(root.length()));            data.put("dirs", dirs);            data.put("files", files);            return RemoteServer.createJSONResponse(NanoHTTPD.Response.Status.OK, data.toString());        }catch (JSONException ex){            return RemoteServer.createPlainTextResponse(NanoHTTPD.Response.Status.INTERNAL_ERROR,  "SERVER INTERNAL ERROR: JSONException: " + ex.getMessage());        }    }

 

9. "/file/download /":The file downloading Service implements the file downloading function of the box.

Code File: FileRequestProcesser. java

Parameters:

None

Call example:

GET/file/download/{path of the downloaded file}

Code implementation:

    private NanoHTTPD.Response downloadFileData(String fileName){        File file = new File(Environment.getExternalStorageDirectory(), fileName);        if(!file.exists()){            return RemoteServer.createPlainTextResponse(NanoHTTPD.Response.Status.NOT_FOUND, "Error 404, file not found.");        }        try{            InputStream inputStream = new FileInputStream(file);            return RemoteServer.newFixedLengthResponse(NanoHTTPD.Response.Status.OK,                    NanoHTTPD.getMimeTypeForFile(file.getName()) + "; charset=utf-8", inputStream, (long)inputStream.available());        } catch (Exception e) {            return RemoteServer.createPlainTextResponse(NanoHTTPD.Response.Status.NOT_FOUND, "Error 404, file not found.");        }    }

 

10. "/file/cut", "/file/copy ":File and directory cutting and copying services.

Code File: FileRequestProcesser. java

Parameters:

Paths = List of directories or files to be operated, separated by "|"

TargetPath = new target directory of the cut or move object

Call example:

POST /file/cut

paths=/Download/a.txt&targetPath=/Andorid/data/
POST /file/copy

paths=/Download/a.txt&targetPath=/Andorid/data/

Code implementation:

   private void batchCopyFile(String targetPath, String paths){        File targetPathFile = new File(Environment.getExternalStorageDirectory(), targetPath);        if(!targetPathFile.exists()) return;        String[] pathData = paths.split("\\|");        for(String p : pathData){            if(!TextUtils.isEmpty(p)) {                File source = new File(Environment.getExternalStorageDirectory(), p);                RemoteServerFileManager.copyFile(source, targetPathFile);            }        }    }    private void batchCutFile(String targetPath, String paths){        File targetPathFile = new File(Environment.getExternalStorageDirectory(), targetPath);        if(!targetPathFile.exists()) return;        String[] pathData = paths.split("\\|");        for(String p : pathData){            if(!TextUtils.isEmpty(p)) {                File source = new File(Environment.getExternalStorageDirectory(), p);                RemoteServerFileManager.cutFile(source, targetPathFile);            }        }    }

 

11. "/file/delete ":File or directory deletion service. If a directory is deleted, all subdirectories and files under the directory are deleted.

Code File: FileRequestProcesser. java

Parameters:

Paths = list of files or directories to be deleted

Call example:

POST /file/delete

paths=/Download/a.txt|/Download/test

Code implementation:

    private void batchDeleteFile(String paths){        String[] pathData = paths.split("\\|");        for(String p : pathData){            if(!TextUtils.isEmpty(p)) {                File path = new File(Environment.getExternalStorageDirectory(), p);                RemoteServerFileManager.deleteFile(path);            }        }    }

 

12. "/file/upload ":File Upload service. This interface is similar to the/upload interface, but this interface uploads files to the current directory on the file management interface, and does not install the APK package and play video files.

Code File: FileRequestProcesser. java

Parameters:

File = uploaded file data

Path = directory for storing uploaded files

Call example:

POST /file/upload

--------

Code implementation:

File Upload has been completed in NanoHTTPD, so you only need to move the uploaded file to the corresponding directory.

    private NanoHTTPD.Response uploadFile(Map<String, String> params, Map<String, String> files){        String uploadFileName  = params.get("file");        String uploadPathName  = params.get("path");        String localFilename = files.get("file");        boolean r = false;        if(!TextUtils.isEmpty(uploadFileName)) {            if (!TextUtils.isEmpty(localFilename)) {                File saveFilename = new File(Environment.getExternalStorageDirectory(), uploadPathName);                File localFile = new File(localFilename);                saveFilename = new File(saveFilename,localFile.getName());                r = localFile.renameTo(saveFilename);            }        }        return RemoteServer.createJSONResponse(NanoHTTPD.Response.Status.OK,  "{\"success\":" + (r ? "true": "false") + "}");    }

 

V. Notes

Project address:Https://github.com/kingthy/TVRemoteIME

Chat QQ group:7149348. You can join the QQ group to share the live video source, feedback, and suggestions.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.