├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── README.md
├── ic_launcher-web.png
├── libs
└── android-support-v4.jar
├── proguard-project.txt
├── project.properties
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-ldpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── layout
│ ├── list_item.xml
│ ├── local_display.xml
│ └── remote_display.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── values
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── adamrocker
└── miracastsample
└── MainActivity.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | gen
2 | bin
3 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MiracastSample
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Miracast Sample
2 |
3 | Test application of Android using Presentation class which displays something on the remote display like a TV over Miracast technology.
4 |
5 | ## Demo
6 | 
7 |
8 | Install this apk to the Nexus4 and display a simple text "Hello world,…" to the remote display which is connected the Miracast receiver(PTV3000 /firmware 2.2.2).
9 |
10 | ## Digest
11 |
12 | #### How to get displays
13 |
14 | DisplayManger handles all displays including the local display.
15 |
16 | mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
17 |
18 | You can get all displays via DisplayManager.
19 |
20 | Display[] displays = mDisplayManager.getDisplays();
21 |
22 |
23 | #### Show the remote display
24 |
25 | Super easy to show something on the remote display. Just call show() method which is implemented in Presentation class provided by Android SDKr17.
26 |
27 | private void showPresentation(Display display) {
28 | RemotePresentation presentation = new RemotePresentation(this, display);
29 | presentation.show();
30 | }
31 |
32 | RemotePresentation class is extended Presentation.
33 | Presentation class looks like Activity. You can set up the display overriding the onCreate method.
34 |
35 | private final class RemotePresentation extends Presentation {
36 | @Override
37 | protected void onCreate(Bundle savedInstanceState) {
38 | super.onCreate(savedInstanceState);
39 | setContentView(R.layout.remote_display);
40 | }
41 | }
42 |
43 | This demo apk shows only TextView on the remote display. The layout resource is remote_display.xml.
44 |
45 |
50 |
51 |
59 |
60 |
61 |
62 |
63 | ## How to setup the miracast environment
64 |
65 | #### Test Enviroinment
66 |
67 | ***Nexus4:*** Currently only Nexus4 supports the Miracast(27 Dec. 2012).
68 |
69 | ***PTV3000:*** I've tested this apk with [PTV3000](http://www.netgear.com/home/products/hometheater/media-players/PTV3000.aspx).
70 |
71 | #### Nexus4
72 |
73 | Turn on the "Wireless Display" on the Settings.
74 |
75 | 
76 |
77 | You can find wireless displays and tap an item to connect.
78 |
79 | 
80 |
81 | #### PTV3000
82 |
83 | Check the firmware version. I bought this gadget from Amazon.com and the version is 1.0.13. TOO LOW!! This version does not support Miracast. You need to update the firmware in 2 steps.
84 |
85 | ***STEP1:*** Download the latest firmware which is on Internet. I could find the version 2.2.2. This might not be official, I guess.
86 |
87 | ***STEP2:*** Update the firmware. See the [Installation Guide (PDF)](http://www.downloads.netgear.com/files/GDC/PTV3000/PTV3000_IG_10AUG2012.pdf)
88 |
89 |
90 |
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-17
15 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adamrocker/Miracast-Sample/a94ca846f471971be6e6a352734720caf83bc21e/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/list_item.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
14 |
22 |
23 |
30 |
--------------------------------------------------------------------------------
/res/layout/local_display.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/res/layout/remote_display.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
15 |
16 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Miracast Sample
4 | Hello world, Remote Display over Miracast!!
5 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/src/com/adamrocker/miracastsample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.adamrocker.miracastsample;
2 |
3 | import android.graphics.Point;
4 | import android.hardware.display.DisplayManager;
5 | import android.media.MediaRouter;
6 | import android.os.Bundle;
7 | import android.app.ActionBar;
8 | import android.app.ActionBar.OnNavigationListener;
9 | import android.app.Activity;
10 | import android.app.Presentation;
11 | import android.content.Context;
12 | import android.util.SparseArray;
13 | import android.view.Display;
14 | import android.view.Menu;
15 | import android.view.View;
16 | import android.view.View.OnClickListener;
17 | import android.view.ViewGroup;
18 | import android.widget.ArrayAdapter;
19 | import android.widget.CheckBox;
20 | import android.widget.CompoundButton;
21 | import android.widget.CompoundButton.OnCheckedChangeListener;
22 | import android.widget.ListView;
23 | import android.widget.TextView;
24 |
25 | public class MainActivity extends Activity {
26 |
27 | private DisplayManager mDisplayManager;
28 | private DisplayListAdapter mDisplayListAdapter;
29 | private ListView mListView;
30 | private final SparseArray mActivePresentations = new SparseArray();
31 |
32 | private final DisplayManager.DisplayListener mDisplayListener = new DisplayManager.DisplayListener() {
33 | @Override
34 | public void onDisplayAdded(int displayId) {
35 | mDisplayListAdapter.updateContents();
36 | }
37 |
38 | @Override
39 | public void onDisplayChanged(int displayId) {
40 | mDisplayListAdapter.updateContents();
41 | }
42 |
43 | @Override
44 | public void onDisplayRemoved(int displayId) {
45 | mDisplayListAdapter.updateContents();
46 | }
47 | };
48 |
49 | @Override
50 | protected void onCreate(Bundle savedInstanceState) {
51 | super.onCreate(savedInstanceState);
52 | setContentView(R.layout.local_display);
53 | mDisplayManager = (DisplayManager)getSystemService(Context.DISPLAY_SERVICE);
54 |
55 | mDisplayListAdapter = new DisplayListAdapter(this);
56 | mListView = (ListView)findViewById(R.id.display_list);
57 | mListView.setAdapter(mDisplayListAdapter);
58 | }
59 |
60 | protected void onResume() {
61 | super.onResume();
62 | mDisplayListAdapter.updateContents();
63 | mDisplayManager.registerDisplayListener(mDisplayListener, null);
64 | }
65 |
66 | private void showPresentation(Display display) {
67 | RemotePresentation presentation = new RemotePresentation(this, display);
68 | mActivePresentations.put(display.getDisplayId(), presentation);
69 | presentation.show();
70 | }
71 |
72 | private void hidePresentation(Display display) {
73 | final int displayId = display.getDisplayId();
74 | RemotePresentation presentation = mActivePresentations.get(displayId);
75 | if (presentation == null) {
76 | return;
77 | }
78 |
79 | presentation.dismiss();
80 | mActivePresentations.delete(displayId);
81 | }
82 |
83 | private final class DisplayListAdapter extends ArrayAdapter {
84 | final Context mContext;
85 | private OnCheckedChangeListener mCheckedRemoteDisplay = new OnCheckedChangeListener() {
86 | @Override
87 | public void onCheckedChanged(CompoundButton view, boolean isChecked) {
88 | synchronized (mCheckedRemoteDisplay) {
89 | final Display display = (Display)view.getTag();
90 | if (isChecked) {
91 | showPresentation(display);
92 | } else {
93 | hidePresentation(display);
94 | }
95 | }
96 | }
97 | };
98 |
99 | public DisplayListAdapter(Context context) {
100 | super(context, R.layout.list_item);
101 | mContext = context;
102 | }
103 |
104 | @Override
105 | public View getView(int position, View convertView, ViewGroup parent) {
106 | final View v;
107 | if (convertView == null) {
108 | v = ((Activity) mContext).getLayoutInflater().inflate(R.layout.list_item, null);
109 | } else {
110 | v = convertView;
111 | }
112 |
113 | final Display display = getItem(position);
114 |
115 | //TITLE
116 | TextView tv = (TextView)v.findViewById(R.id.display_id);
117 | tv.setText(display.getName() + "( ID: " + display.getDisplayId() + " )");
118 |
119 | //DESCRIPTION
120 | tv = (TextView)v.findViewById(R.id.display_desc);
121 | tv.setText(display.toString());
122 |
123 | //SHOW or HIDE the presentation
124 | CheckBox cb = (CheckBox)v.findViewById(R.id.display_cb);
125 | cb.setTag(display);
126 | cb.setOnCheckedChangeListener(mCheckedRemoteDisplay);
127 | return v;
128 | }
129 |
130 | public void updateContents() {
131 | clear();
132 |
133 | Display[] displays = mDisplayManager.getDisplays();
134 | addAll(displays);
135 | }
136 | }
137 |
138 | private final class RemotePresentation extends Presentation {
139 | public RemotePresentation(Context context, Display display) {
140 | super(context, display);
141 | }
142 |
143 | @Override
144 | protected void onCreate(Bundle savedInstanceState) {
145 | super.onCreate(savedInstanceState);
146 | setContentView(R.layout.remote_display);
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------