Skip to content

Commit 394b061

Browse files
committed
added a demo for controlling LEDs through an Arduino ADK from an Android device
1 parent e963de1 commit 394b061

File tree

28 files changed

+785
-0
lines changed

28 files changed

+785
-0
lines changed

AndroidArduinoLEDControl/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.gradle
2+
/local.properties
3+
/.idea/workspace.xml
4+
.DS_Store
5+
/build
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 20
5+
buildToolsVersion "20.0.0"
6+
7+
defaultConfig {
8+
applicationId "com.ptrprograms.androidarduinoledcontrol"
9+
minSdkVersion 16
10+
targetSdkVersion 20
11+
versionCode 1
12+
versionName "1.0"
13+
}
14+
buildTypes {
15+
release {
16+
runProguard false
17+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18+
}
19+
}
20+
}
21+
22+
dependencies {
23+
compile fileTree(dir: 'libs', include: ['*.jar'])
24+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Add project specific ProGuard rules here.
2+
# By default, the flags in this file are appended to flags specified
3+
# in /Applications/Android Studio.app/sdk/tools/proguard/proguard-android.txt
4+
# You can edit the include path and order by changing the proguardFiles
5+
# directive in build.gradle.
6+
#
7+
# For more details, see
8+
# http://developer.android.com/guide/developing/tools/proguard.html
9+
10+
# Add any project specific keep options here:
11+
12+
# If your project uses WebView with JS, uncomment the following
13+
# and specify the fully qualified class name to the JavaScript interface
14+
# class:
15+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16+
# public *;
17+
#}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.ptrprograms.androidarduinoledcontrol;
2+
3+
import android.app.Application;
4+
import android.test.ApplicationTestCase;
5+
6+
/**
7+
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
8+
*/
9+
public class ApplicationTest extends ApplicationTestCase<Application> {
10+
public ApplicationTest() {
11+
super(Application.class);
12+
}
13+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
package="com.ptrprograms.androidarduinoledcontrol" >
4+
5+
<uses-feature android:name="android.hardware.usb.accessory" />
6+
7+
<application
8+
android:allowBackup="true"
9+
android:icon="@drawable/ic_launcher"
10+
android:label="@string/app_name"
11+
android:theme="@style/AppTheme" >
12+
<activity
13+
android:name=".MainActivity"
14+
android:label="@string/app_name" >
15+
<intent-filter>
16+
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
17+
</intent-filter>
18+
19+
<intent-filter>
20+
<action android:name="android.intent.action.MAIN" />
21+
22+
<category android:name="android.intent.category.LAUNCHER" />
23+
</intent-filter>
24+
25+
<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
26+
android:resource="@xml/accessories" />
27+
</activity>
28+
</application>
29+
30+
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
package com.ptrprograms.androidarduinoledcontrol;
2+
3+
import android.app.Fragment;
4+
import android.app.PendingIntent;
5+
import android.content.BroadcastReceiver;
6+
import android.content.Context;
7+
import android.content.Intent;
8+
import android.content.IntentFilter;
9+
import android.hardware.usb.UsbAccessory;
10+
import android.hardware.usb.UsbManager;
11+
import android.os.Bundle;
12+
import android.os.ParcelFileDescriptor;
13+
import android.view.LayoutInflater;
14+
import android.view.View;
15+
import android.view.ViewGroup;
16+
import android.widget.SeekBar;
17+
import android.widget.TextView;
18+
import android.widget.Toast;
19+
20+
import java.io.FileDescriptor;
21+
import java.io.FileOutputStream;
22+
import java.io.IOException;
23+
24+
/**
25+
* Created by Paul Trebilcox-Ruiz on 7/27/14.
26+
*/
27+
public class LEDControlFragment extends Fragment implements SeekBar.OnSeekBarChangeListener {
28+
29+
private static final String EXTRA_ACCESSORY = "extra_accessory";
30+
private static final String ACTION_USB_PERMISSION = "com.ptrprograms.androidarduinoledcontrol.action.USB_PERMISSION";
31+
32+
private UsbManager mUsbManager;
33+
private UsbAccessory mUsbAccessory;
34+
private PendingIntent mPermissionIntent;
35+
private boolean mPermissionRequestPending;
36+
private ParcelFileDescriptor mFileDescriptor;
37+
38+
private FileOutputStream mOutputStream;
39+
40+
private TextView mRedLEDValueTV;
41+
private TextView mGreenLEDValueTV;
42+
private TextView mBlueLEDValueTV;
43+
44+
private SeekBar mRedLEDSeekBar;
45+
private SeekBar mGreenLEDSeekBar;
46+
private SeekBar mBlueLEDSeekBar;
47+
48+
@Override
49+
public void onCreate(Bundle savedInstanceState) {
50+
super.onCreate(savedInstanceState);
51+
52+
mUsbManager = (UsbManager) getActivity().getSystemService( Context.USB_SERVICE );
53+
mPermissionIntent = PendingIntent.getBroadcast( getActivity(), 0, new Intent( ACTION_USB_PERMISSION ), 0 );
54+
IntentFilter filter = new IntentFilter( ACTION_USB_PERMISSION );
55+
filter.addAction( UsbManager.ACTION_USB_ACCESSORY_DETACHED );
56+
getActivity().registerReceiver( mUsbReceiver, filter );
57+
58+
if( savedInstanceState != null && savedInstanceState.containsKey( EXTRA_ACCESSORY ) ) {
59+
mUsbAccessory = savedInstanceState.getParcelable( EXTRA_ACCESSORY );
60+
openAccessory( mUsbAccessory );
61+
}
62+
63+
setRetainInstance( true );
64+
65+
}
66+
67+
@Override
68+
public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
69+
View view = inflater.inflate( R.layout.fragment_main, container );
70+
mRedLEDValueTV = (TextView) view.findViewById( R.id.red_led_value );
71+
mRedLEDSeekBar = (SeekBar) view.findViewById( R.id.red_led_seek_bar );
72+
mRedLEDSeekBar.setOnSeekBarChangeListener( this );
73+
74+
mGreenLEDValueTV = (TextView) view.findViewById( R.id.green_led_value );
75+
mGreenLEDSeekBar = (SeekBar) view.findViewById( R.id.green_led_seek_bar );
76+
mGreenLEDSeekBar.setOnSeekBarChangeListener( this );
77+
78+
mBlueLEDValueTV = (TextView) view.findViewById( R.id.blue_led_value );
79+
mBlueLEDSeekBar = (SeekBar) view.findViewById( R.id.blue_led_seek_bar );
80+
mBlueLEDSeekBar.setOnSeekBarChangeListener( this );
81+
82+
mRedLEDValueTV.setText( String.valueOf( mRedLEDSeekBar.getProgress() ) );
83+
mGreenLEDValueTV.setText( String.valueOf( mGreenLEDSeekBar.getProgress() ) );
84+
mBlueLEDValueTV.setText( String.valueOf( mBlueLEDSeekBar.getProgress() ) );
85+
86+
return view;
87+
}
88+
89+
private void openAccessory(UsbAccessory accessory) {
90+
if( accessory == null )
91+
return;
92+
93+
mFileDescriptor = mUsbManager.openAccessory( accessory );
94+
if (mFileDescriptor != null ) {
95+
mUsbAccessory = accessory;
96+
FileDescriptor fileDescriptor = mFileDescriptor.getFileDescriptor();
97+
mOutputStream = new FileOutputStream( fileDescriptor );
98+
}
99+
}
100+
101+
@Override
102+
public void onResume() {
103+
super.onResume();
104+
105+
if( mOutputStream != null ) {
106+
return;
107+
}
108+
109+
UsbAccessory[] accessories = mUsbManager.getAccessoryList();
110+
UsbAccessory accessory = ( accessories == null ? null : accessories[0] );
111+
if( accessory != null ) {
112+
if( mUsbManager.hasPermission( accessory ) ) {
113+
openAccessory( accessory );
114+
} else {
115+
synchronized( mUsbReceiver ) {
116+
if( !mPermissionRequestPending ) {
117+
mUsbManager.requestPermission( accessory, mPermissionIntent );
118+
mPermissionRequestPending = true;
119+
}
120+
}
121+
}
122+
}
123+
}
124+
125+
@Override
126+
public void onPause() {
127+
super.onPause();
128+
closeAccessory();
129+
}
130+
131+
@Override
132+
public void onDestroy() {
133+
getActivity().unregisterReceiver( mUsbReceiver );
134+
super.onDestroy();
135+
}
136+
137+
private void closeAccessory() {
138+
try {
139+
if( mFileDescriptor != null ) {
140+
mFileDescriptor.close();
141+
}
142+
} catch ( IOException e ) {
143+
} finally {
144+
mFileDescriptor = null;
145+
mUsbAccessory = null;
146+
}
147+
}
148+
149+
150+
@Override
151+
public void onSaveInstanceState( Bundle outState ) {
152+
super.onSaveInstanceState( outState );
153+
outState.putParcelable( EXTRA_ACCESSORY, mUsbAccessory );
154+
}
155+
156+
private void writeToArduin( byte LEDNum, int value ) {
157+
byte[] buffer = new byte[2];
158+
if( value > 255 ) {
159+
value = 255;
160+
} else if( value < 0 ) {
161+
value = 0;
162+
}
163+
164+
buffer[0] = LEDNum;
165+
buffer[1] = (byte) value;
166+
167+
if( mOutputStream != null ) {
168+
try {
169+
mOutputStream.write( buffer );
170+
} catch( IOException e ) {
171+
Toast.makeText( getActivity(), "Something went wrong when writing to the Arduino", Toast.LENGTH_LONG ).show();
172+
}
173+
}
174+
}
175+
176+
@Override
177+
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
178+
switch( seekBar.getId() ) {
179+
case R.id.red_led_seek_bar: {
180+
mRedLEDValueTV.setText( String.valueOf( seekBar.getProgress() ) );
181+
writeToArduin( (byte) 0, seekBar.getProgress() );
182+
break;
183+
}
184+
case R.id.green_led_seek_bar: {
185+
mGreenLEDValueTV.setText( String.valueOf( seekBar.getProgress() ) );
186+
writeToArduin( (byte) 1, seekBar.getProgress() );
187+
break;
188+
}
189+
case R.id.blue_led_seek_bar: {
190+
mBlueLEDValueTV.setText( String.valueOf( seekBar.getProgress() ) );
191+
writeToArduin( (byte) 2, seekBar.getProgress() );
192+
break;
193+
}
194+
}
195+
}
196+
197+
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
198+
@Override
199+
public void onReceive(Context context, Intent intent) {
200+
String action = intent.getAction();
201+
if( ACTION_USB_PERMISSION.equals( action ) ) {
202+
UsbAccessory accessory = intent.getParcelableExtra( UsbManager.EXTRA_ACCESSORY );
203+
if( intent.getBooleanExtra( UsbManager.EXTRA_PERMISSION_GRANTED, false ) ) {
204+
openAccessory( accessory );
205+
}
206+
207+
mPermissionRequestPending = false;
208+
} else if( UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals( action ) ) {
209+
UsbAccessory accessory = intent.getParcelableExtra( UsbManager.EXTRA_ACCESSORY );
210+
if( accessory != null && accessory.equals( mUsbAccessory ) ) {
211+
closeAccessory();
212+
}
213+
}
214+
}
215+
};
216+
217+
@Override
218+
public void onStartTrackingTouch(SeekBar seekBar) {
219+
220+
}
221+
222+
@Override
223+
public void onStopTrackingTouch(SeekBar seekBar) {
224+
225+
}
226+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.ptrprograms.androidarduinoledcontrol;
2+
3+
import android.app.Activity;
4+
import android.os.Bundle;
5+
6+
/**
7+
* Created by Paul Trebilcox-Ruiz on 7/27/14.
8+
*/
9+
public class MainActivity extends Activity {
10+
11+
@Override
12+
protected void onCreate( Bundle savedInstanceState ) {
13+
super.onCreate( savedInstanceState );
14+
setContentView( R.layout.activity_main );
15+
}
16+
}
Loading
Loading
Loading
Loading
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:id="@+id/main_browse_fragment"
3+
android:name="com.ptrprograms.androidarduinoledcontrol.LEDControlFragment"
4+
android:layout_width="match_parent"
5+
android:layout_height="match_parent"
6+
android:paddingLeft="@dimen/activity_horizontal_margin"
7+
android:paddingRight="@dimen/activity_horizontal_margin"
8+
android:paddingTop="@dimen/activity_vertical_margin"
9+
android:paddingBottom="@dimen/activity_vertical_margin"/>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:layout_width="match_parent"
3+
android:layout_height="match_parent">
4+
5+
<TextView
6+
android:id="@+id/red_led_value"
7+
android:layout_width="match_parent"
8+
android:layout_height="wrap_content"
9+
android:gravity="center"/>
10+
<SeekBar
11+
android:id="@+id/red_led_seek_bar"
12+
android:max="255"
13+
android:layout_width="match_parent"
14+
android:layout_height="wrap_content"
15+
android:layout_below="@id/red_led_value"/>
16+
<TextView
17+
android:id="@+id/green_led_value"
18+
android:layout_width="match_parent"
19+
android:layout_height="wrap_content"
20+
android:layout_below="@id/red_led_seek_bar"
21+
android:paddingTop="12dp"
22+
android:gravity="center"/>
23+
<SeekBar
24+
android:id="@+id/green_led_seek_bar"
25+
android:max="255"
26+
android:layout_width="match_parent"
27+
android:layout_height="wrap_content"
28+
android:layout_below="@id/green_led_value"/>
29+
<TextView
30+
android:id="@+id/blue_led_value"
31+
android:layout_width="match_parent"
32+
android:layout_height="wrap_content"
33+
android:layout_below="@id/green_led_seek_bar"
34+
android:paddingTop="12dp"
35+
android:gravity="center"/>
36+
<SeekBar
37+
android:id="@+id/blue_led_seek_bar"
38+
android:max="255"
39+
android:layout_width="match_parent"
40+
android:layout_height="wrap_content"
41+
android:layout_below="@id/blue_led_value"/>
42+
43+
</RelativeLayout>

0 commit comments

Comments
 (0)