Java tutorial
/*############################### # AUTHOR: Vincent Olislagers # # DATE: 19-9-2012 # # CIID.dk Frugal Digital # # LICENSE CC NC SA 3.0 # ###############################*/ package dk.ciid.android.infobooth.activities; /* ARDUINO COMMUNICATION IMPORTS */ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import com.android.future.usb.UsbAccessory; import com.android.future.usb.UsbManager; import dk.ciid.android.infobooth.xml.XMLParser; /* ARDUINO COMMUNICATION IMPORTS */ /* XML PARSING IMPORTS */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; /* XML PARSING IMPORTS */ import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import android.media.MediaPlayer; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.ParcelFileDescriptor; import android.renderscript.Font; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.Color; import android.graphics.Typeface; import android.util.Log; import android.view.GestureDetector; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.GestureDetector.OnGestureListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import android.telephony.gsm.SmsManager; import android.app.PendingIntent; public class IntroductionActivity extends Activity implements OnGestureListener { /* Declaration of variables received through Intent */ private static boolean isInDebugMode; private static ArrayList<String> serviceIdItems; private static ArrayList<String> serviceNameItems; private static ArrayList<String> serviceDescItems; private static String voice1; private static String voice2; private static String voice3; private static String voice4; private static String voice5; private static String voice6; /* Declaration of variables received through Intent */ /* XML PARSING ******************************************************************/ static final String token = "HA6D3KA502H2J3K4C0AG"; static final String URL = "http://ciid.dk/frugalsms/app/list.php?token=" + token; // XML node keys static final String KEY_SERVICE = "service"; // parent node static final String KEY_NAME = "name"; static final String KEY_DESCRIPTION = "description"; /* XML PARSING ******************************************************************/ /* ARDUINO COMMUNICATION DECLARATIONS ********************************************/ // TAG is used to debug in Android logcat console // The constant TAG is an identifier for the current class and is used only for logging purposes in // Android. If you have a look at the logcat view in Eclipse while a device or an emulator is running, you // will see that logged messages are associated to a TAG, which simplifies reading the log output. ( private static final String TAG = IntroductionActivity.class.getSimpleName();; private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION"; //private static final String ACTION_USB_PERMISSION = "com.android.example.USB_PERMISSION"; // Establishing a connection to an external device has to be permitted by the user. When the user is // granting the rights to connect to your ADK board, the PendingIntent will broadcast the // ACTION_USB_PERMISSION with a flag reflecting whether the user confirmed or denied the access. The // Boolean variable mPermissionRequestPending is only used to not show the permission dialog again if the // user interaction is still pending. private PendingIntent mPermissionIntent; private boolean mPermissionRequestPending; // The UsbManager is a system service that manages all interaction with the USB port of the device. It is // used to enumerate the connected devices and to request and check the permission to connect to an // accessory. The UsbManager is also responsible for opening the connection to the external device. The // UsbAccessory is a reference to the connected accessory. The ParcelFileDescriptor is obtained when the // connection to the accessory is established. It is used to get access to the input- and output stream of the // accessory private UsbManager mUsbManager; private UsbAccessory mAccessory; private ParcelFileDescriptor mFileDescriptor; private FileInputStream mInputStream; private FileOutputStream mOutputStream; // COMMAND_TEXT and TARGET_DEFAULT are the same constants as the ones used in the Arduino sketch. // They make up the first two bytes of the data protocol. private static final byte COMMAND_TEXT = 0xF; private static final byte TARGET_DEFAULT = 0xF; private static final byte KEYPAD_COMMAND = 0x1; private static final byte COIN_COMMAND = 0x2; private static final byte BUTTON_COMMAND = 0x3; /* ARDUINO COMMUNICATION DECLARATIONS ********************************************/ /* GESTURE STUFF ********************************************/ private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250; private static final int SWIPE_THRESHOLD_VELOCITY = 200; private GestureDetector gestureScanner; /* GESTURE STUFF ********************************************/ /* SOUND STUFF ************************************************************/ MediaPlayer mediaPlayer; private int stateMediaPlayer = 1; private final int stateMP_Error = 0; private final int stateMP_NotStarter = 1; private final int stateMP_Playing = 2; private final int stateMP_Pausing = 3; /* SOUND STUFF ************************************************************/ @Override public void onCreate(Bundle savedInstanceState) { /* Variables received through Intent */ Intent openActivity = getIntent(); // this is just for example purpose isInDebugMode = openActivity.getBooleanExtra("isInDebugMode", true); // should the app send a welcome sms after subscribing? voice1 = openActivity.getStringExtra("voice1"); // path to voice file 1 voice2 = openActivity.getStringExtra("voice2"); // path to voice file 2 voice3 = openActivity.getStringExtra("voice3"); // path to voice file 3 voice4 = openActivity.getStringExtra("voice4"); // path to voice file 4 voice5 = openActivity.getStringExtra("voice5"); // path to voice file 5 voice6 = openActivity.getStringExtra("voice6"); // path to voice file 6 /* Variables received through Intent */ super.onCreate(savedInstanceState); /* ARDUINO COMMUNICATION STUFF ********************************************/ // a reference to the USB system service is obtained so that you can call its methods later on mUsbManager = UsbManager.getInstance(this); mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0); IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION); filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED); registerReceiver(mUsbReceiver, filter); if (getLastNonConfigurationInstance() != null) { mAccessory = (UsbAccessory) getLastNonConfigurationInstance(); openAccessory(mAccessory); } /* ARDUINO COMMUNICATION STUFF ********************************************/ gestureScanner = new GestureDetector(this); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_introduction); // Set up sound playback initMediaPlayer(); runOnUiThread(new Runnable() { public void run() { if (isInDebugMode) Toast.makeText(getApplicationContext(), "Debug mode is ON", Toast.LENGTH_SHORT).show(); } }); } @Override public boolean onTouchEvent(MotionEvent me) { return gestureScanner.onTouchEvent(me); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } public boolean onDown(MotionEvent e) { // TODO Auto-generated method stub return false; } public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) return false; // right to left swipe if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // go to the next screen changeActivity("dk.ciid.android.infobooth.activities.INFORMATIONSERVICEACTIVITY"); } // left to right swipe else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { } // bottom to top swipe else if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // top to bottom swipe } else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { } } catch (Exception e) { // nothing } return true; } public void onLongPress(MotionEvent e) { // TODO Auto-generated method stub } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { // TODO Auto-generated method stub return false; } public void onShowPress(MotionEvent e) { // TODO Auto-generated method stub } public boolean onSingleTapUp(MotionEvent e) { // TODO Auto-generated method stub return false; } //---sends an SMS message to another device--- private void sendSMS(String phoneNumber, String message) { PendingIntent pi = PendingIntent.getActivity(this, 0, new Intent(this, IntroductionActivity.class), 0); SmsManager sms = SmsManager.getDefault(); sms.sendTextMessage(phoneNumber, null, message, pi, null); } /* ARDUINO COMMUNICATION STUFF ******************************************************************/ @Override public Object onRetainNonConfigurationInstance() { if (mAccessory != null) { return mAccessory; } else { return super.onRetainNonConfigurationInstance(); } } /** Called when the activity is resumed from its paused state and immediately after onCreate(). */ @Override public void onResume() { super.onResume(); //************************************ if (getLastNonConfigurationInstance() != null) { mAccessory = (UsbAccessory) getLastNonConfigurationInstance(); openAccessory(mAccessory); } //***************************************** // check if you are still able to communicate with the accessory. if (mInputStream != null && mOutputStream != null) { return; } /* If the input- and outputstream is still active you are good to go for communication and can return // prematurely from the onResume method. Otherwise, you have to get a reference of the accessory from the // UsbManager. If you already have the users permission to communicate with the device you can open and // reassign the input- and outputstreams. This part is implemented in an own method called // openAccessory,*/ UsbAccessory[] accessories = mUsbManager.getAccessoryList(); UsbAccessory accessory = (accessories == null ? null : accessories[0]); if (accessory != null) { if (mUsbManager.hasPermission(accessory)) { openAccessory(accessory); } else { synchronized (mUsbReceiver) { if (!mPermissionRequestPending) { mUsbManager.requestPermission(accessory, mPermissionIntent); mPermissionRequestPending = true; } } } } else { Log.d(TAG, "mAccessory is null"); } /* SOUND STUFF **********************************************************************************/ switch (stateMediaPlayer) { case stateMP_Error: break; case stateMP_NotStarter: if (isInDebugMode) Toast.makeText(getApplicationContext(), "Playing sound", Toast.LENGTH_SHORT).show(); else mediaPlayer.start(); stateMediaPlayer = stateMP_Playing; break; case stateMP_Playing: mediaPlayer.pause(); stateMediaPlayer = stateMP_Pausing; break; case stateMP_Pausing: if (isInDebugMode) Toast.makeText(getApplicationContext(), "Playing sound", Toast.LENGTH_SHORT).show(); else mediaPlayer.start(); stateMediaPlayer = stateMP_Playing; break; } /* SOUND STUFF **********************************************************************************/ ParseServices parseServ = new ParseServices(); parseServ.execute(new String[] { URL }); } @Override public void onPause() { super.onPause(); closeAccessory(); } /** Called when the activity is no longer needed prior to being removed from the activity stack. */ @Override public void onDestroy() { // deinitialize the broadcast receiver that communicates with Arduino unregisterReceiver(mUsbReceiver); super.onDestroy(); } /* The broadcast receiver is implemented as an anonymous inner class for the type BroadcastReceiver. The only method youll have to overwrite is the onReceive method which is called by the system if this broadcast receiver is registered and matches the provided intent-filter. Remember that two actions are defined in the intent-filter. You will have to check which action occurred when the broadcast receiver is called. If you receive the action describing that a permission request has been answered youll have to check if the user granted permission to communicate with your accessory. If so, you can open the communication channels of the accessory. The second action which could have triggered the broadcast receiver is the notification that the accessory has been detached from the Android device. In that case, you need to clean up and close your communication channels. As you can see, the BroadcastReceiver calls the openAccessory method and the closeAccessory method to open and close the communication channels to the accessory. */ private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (ACTION_USB_PERMISSION.equals(action)) { synchronized (this) { UsbAccessory accessory = UsbManager.getAccessory(intent); if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { openAccessory(accessory); } else { Log.d(TAG, "permission denied for accessory " + accessory); } mPermissionRequestPending = false; } } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) { UsbAccessory accessory = UsbManager.getAccessory(intent); if (accessory != null && accessory.equals(mAccessory)) { closeAccessory(); } } } }; private void openAccessory(UsbAccessory accessory) { mFileDescriptor = mUsbManager.openAccessory(accessory); if (mFileDescriptor != null) { mAccessory = accessory; FileDescriptor fd = mFileDescriptor.getFileDescriptor(); mInputStream = new FileInputStream(fd); mOutputStream = new FileOutputStream(fd); Thread thread = new Thread(null, commRunnable, TAG); thread.start(); Log.d(TAG, "accessory opened"); } else { Log.d(TAG, "accessory open fail"); } } /* All closeAccessory() does is close the accessorys FileDescriptor. The system will handle all underlying OS resources associated with its streams. When you finally open a connection to the accessory, you can send and receive data back and forth. */ private void closeAccessory() { try { if (mFileDescriptor != null) { mFileDescriptor.close(); } } catch (IOException e) { } finally { mFileDescriptor = null; mAccessory = null; } } volatile Runnable commRunnable = new Runnable() { //@Override public void run() { int ret = 0; final byte[] buffer = new byte[255]; while (ret >= 0) { try { ret = mInputStream.read(buffer); } catch (IOException e) { break; } switch (buffer[0]) { case KEYPAD_COMMAND: break; case BUTTON_COMMAND: if (buffer[3] == 1) { // Green button = Confirm / next screen // go to the next screen changeActivity("dk.ciid.android.infobooth.activities.INFORMATIONSERVICEACTIVITY"); } if (buffer[3] == 2) { // Red button = Cancel / back screen // do nothing } if (buffer[3] == 3) { // Up button = Go up one list element // do nothing } if (buffer[3] == 4) { // Down button = Go down one list element // do nothing } break; default: Log.d(TAG, "unknown msg: " + buffer[0]); break; } } } }; /* ARDUINO COMMUNICATION STUFF ******************************************************************/ /* SOUND STUFF **********************************************************************************/ private void initMediaPlayer() { String PATH_TO_FILE = voice1; mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(PATH_TO_FILE); mediaPlayer.prepare(); //Toast.makeText(this, PATH_TO_FILE, Toast.LENGTH_LONG).show(); stateMediaPlayer = stateMP_NotStarter; } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); //Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show(); stateMediaPlayer = stateMP_Error; } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); //Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show(); stateMediaPlayer = stateMP_Error; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); //Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show(); stateMediaPlayer = stateMP_Error; } } /* SOUND STUFF **********************************************************************************/ // this function is used to navigate from 'screen' to 'screen' private void changeActivity(String activityName) { Intent openActivity = new Intent(activityName); openActivity.putExtra("isInDebugMode", isInDebugMode); openActivity.putExtra("serviceNameItems", serviceNameItems); openActivity.putExtra("serviceDescItems", serviceDescItems); openActivity.putExtra("voice1", voice1); openActivity.putExtra("voice2", voice2); openActivity.putExtra("voice3", voice3); openActivity.putExtra("voice4", voice4); openActivity.putExtra("voice5", voice5); openActivity.putExtra("voice6", voice6); openActivity.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); startActivity(openActivity); closeAccessory(); } /* CLASS FOR XML PARSING OF SERVICES AND DESCRIPTIONS **********************************************************************************/ // this code needs to run in an AsyncTask otherwise Android will throw errors private class ParseServices extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { // params[0] = url to php generated XML file, params[1] = phonenumber, params[2] = subscribedServices, params[3] = expirationDate String url = params[0]; // url to XML file Log.d(TAG, params[0]); // prints path to php file that connects to the database // try { // Create a new HttpClient and Post Header HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost(url); /* XML PARSING *********************************************************** */ // USE ASYNCTASK LIKE IN SUBSCRIPTIONFINALACTIVITY serviceNameItems = new ArrayList<String>(); serviceDescItems = new ArrayList<String>(); XMLParser parser = new XMLParser(); // next line is where the program breaks String xml = parser.getXmlFromUrl(url); // getting XML Document doc = parser.getDomElement(xml); // getting DOM element NodeList nl = doc.getElementsByTagName(KEY_SERVICE); // looping through all item nodes <item> for (int i = 0; i < nl.getLength(); i++) { // creating new HashMap //HashMap<String, String> map = new HashMap<String, String>(); Element e = (Element) nl.item(i); // adding each child node to HashMap key => value //map.put(KEY_NAME, parser.getValue(e, KEY_NAME)); //map.put(KEY_DESCRIPTION, parser.getValue(e, KEY_DESCRIPTION)); Log.d(TAG, "name = " + parser.getValue(e, KEY_NAME)); Log.d(TAG, "description = " + parser.getValue(e, KEY_DESCRIPTION)); // adding service name to serviceNameItems array list serviceNameItems.add(parser.getValue(e, KEY_NAME)); // adding service description to serviceDescItems array list serviceDescItems.add(parser.getValue(e, KEY_DESCRIPTION)); } /* XML PARSING *********************************************************** */ /*} finally { serviceNameItems = new ArrayList<String>(); serviceDescItems = new ArrayList<String>(); serviceNameItems.add("No services downloaded"); serviceDescItems.add("No service descriptions downloaded"); Log.d(TAG, "No internet connection - Couldn't download service list"); runOnUiThread(new Runnable() { public void run() { if(isInDebugMode) Toast.makeText(getApplicationContext(), "No internet connection - Couldn't download service list", Toast.LENGTH_SHORT).show(); } }); }*/ // we need to return a string otherwise AsyncTask complains return params[0]; // return url to php database insert file } @Override protected void onPostExecute(String result) { } } /* CLASS FOR XML PARSING OF SERVICES AND DESCRIPTIONS **********************************************************************************/ }