Commit 1df8752d authored by djamel's avatar djamel

Mise à jour de l'application pour être compatible avec un serveur.

Le serveur enregistre dans sa base de donnée les billets scanné afin
qu'un même billet ne puisse être scanné deux fois. Il retourne également
à l'application le nombre de billet restant.
parent 7a4219fc
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
......@@ -5,7 +5,7 @@
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.4" />
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.14.1" />
<option name="gradleJvm" value="1.7" />
<option name="modules">
<set>
......@@ -13,6 +13,12 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="myModules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
......
......@@ -2,7 +2,9 @@
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AndroidLintDeprecated" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AndroidLintLabelFor" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AndroidLintRtlHardcoded" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="AndroidLintSuspicious0dp" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -12,10 +12,7 @@
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
<afterSyncTasks>
<task>generateDebugAndroidTestSources</task>
<task>generateDebugSources</task>
</afterSyncTasks>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
......@@ -28,7 +25,7 @@
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/test/debug" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
......@@ -50,6 +47,15 @@
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
......@@ -57,6 +63,7 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
......@@ -64,32 +71,54 @@
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/19.1.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-appindexing/8.1.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.google.android.gms/play-services-basement/8.1.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
</content>
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="httpclient-4.3.6" level="project" />
<orderEntry type="library" exported="" name="play-services-basement-8.1.0" level="project" />
<orderEntry type="library" exported="" name="play-services-appindexing-8.1.0" level="project" />
<orderEntry type="library" exported="" name="appcompat-v7-19.1.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-19.1.0" level="project" />
<orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
<orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
<orderEntry type="library" exported="" name="android-async-http-1.4.9" level="project" />
<orderEntry type="library" exported="" name="1_android-async-http-1.4.9" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="hamcrest-core-1.3" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="junit-4.12" level="project" />
</component>
</module>
\ No newline at end of file
......@@ -23,4 +23,6 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:19.1.0'
compile 'com.loopj.android:android-async-http:1.4.9'
compile 'com.google.android.gms:play-services-appindexing:8.1.0'
}
......@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="djamelfel.gala" >
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/gala_logo"
......@@ -11,15 +13,15 @@
<activity
android:name=".Read_QR_Code"
android:label="@string/app_name">
</activity>
<activity
android:name=".Login"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Settings"
android:label="@string/settings">
</activity>
</application>
</manifest>
</manifest>
\ No newline at end of file
package djamelfel.gala;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
/**
* Created by djamel on 08/11/15.
*/
public class Billet implements Serializable, Parcelable{
private String id_billet;
private int quantity;
private int prod_validate;
public Billet(String id_billet, int quantity) {
this.id_billet = id_billet;
this.quantity = quantity;
this.prod_validate = 1;
}
public Billet(String save) {
String[] str = save.split(" ");
this.id_billet = str[0];
this.quantity = Integer.parseInt(str[1]);
this.prod_validate = Integer.parseInt(str[2]);
}
protected Billet(Parcel in) {
this.id_billet = in.readString();
this.quantity = in.readInt();
this.prod_validate = in.readInt();
}
public String getId_billet() {
return this.id_billet;
}
public void validatePlace() {
this.prod_validate++;
}
public boolean isClickable() {
if(this.quantity < this.prod_validate)
return true;
return false;
}
@Override
public int describeContents() {
return 0;
}
public String writeToFile() {
return id_billet + " " + String.valueOf(quantity) + " " + String.valueOf(prod_validate);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id_billet);
dest.writeInt(this.quantity);
dest.writeInt(this.prod_validate);
}
public static final Creator<Billet> CREATOR = new Creator<Billet>() {
@Override
public Billet createFromParcel(Parcel in) {
return new Billet(in);
}
@Override
public Billet[] newArray(int size) {
return new Billet[size];
}
};
}
......@@ -3,10 +3,12 @@ package djamelfel.gala;
import android.os.Parcel;
import android.os.Parcelable;
import java.io.Serializable;
/**
* Created by djamel on 17/10/15.
*/
public class Key_List implements Parcelable {
public class Key_List implements Parcelable, Serializable {
int id;
String key;
......
package djamelfel.gala;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import org.apache.http.conn.util.InetAddressUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import cz.msebera.android.httpclient.Header;
public class Login extends ActionBarActivity implements View.OnClickListener {
private EditText _ipAddress;
private EditText _portNumber;
private ArrayList<Key_List> key_list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
_ipAddress = (EditText)findViewById(R.id.text_ipAddress);
_portNumber = (EditText)findViewById(R.id.text_port);
Button validateIPAddress = (Button) findViewById(R.id.button_ipAddress);
validateIPAddress.setOnClickListener(this);
key_list = new ArrayList<Key_List>();
}
@Override
public void onClick(View vue) {
String myIpString = _ipAddress.getText().toString();
String myPortString = _portNumber.getText().toString();
final String server = "http://" + myIpString + ":" + myPortString;
// check if ip address is right
if (InetAddressUtils.isIPv4Address(myIpString)) {
AsyncHttpClient client = new AsyncHttpClient();
client.get(server + "/keys", new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
JSONObject element;
try {
for (int index = 0; index < response.length(); index++) {
element = response.getJSONObject(index);
Key_List key = new Key_List(element.getInt("id"), element.getString
("key"));
key_list.add(key);
}
} catch (JSONException e) {
e.printStackTrace();
}
//Send key_list to next activity
Intent intent = new Intent(Login.this, Read_QR_Code.class);
intent.putParcelableArrayListExtra("key_list", key_list);
intent.putExtra("server", server);
startActivity(intent);
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
display(getString(R.string.serverError), false);
}
});
}
else {
display(getString(R.string.errorIP), false);
}
}
public void display(String msg, boolean success) {
LayoutInflater inflater = getLayoutInflater();
View layout;
if(success) {
layout = inflater.inflate(R.layout.toast_success,
(ViewGroup) findViewById(R.id.toast_success));
}
else {
layout = inflater.inflate(R.layout.toast_failure,
(ViewGroup) findViewById(R.id.toast_failure));
}
TextView text = (TextView)layout.findViewById(R.id.text);
text.setTextSize(20);
text.setText(msg.toUpperCase());
Toast toast = new Toast(getApplicationContext());
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
}
}
\ No newline at end of file
......@@ -8,15 +8,22 @@ import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.JsonHttpResponseHandler;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
......@@ -26,12 +33,17 @@ import java.util.Iterator;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.entity.StringEntity;
public class Read_QR_Code extends ActionBarActivity implements View.OnClickListener {
static final String ACTION_SCAN = "com.google.zxing.client.android.SCAN";
private ArrayList<Key_List> key_list;
private ArrayList<Key_List> key_list = null;
private String server;
private EditText _nbrPlace;
private EditText _barCode;
@Override
protected void onCreate(Bundle savedInstanceState) {
......@@ -41,23 +53,33 @@ public class Read_QR_Code extends ActionBarActivity implements View.OnClickListe
Intent intent = getIntent();
if (intent != null) {
key_list = intent.getParcelableArrayListExtra("key_list");
server = intent.getStringExtra("server");
}
findViewById(R.id.ButtonBarCode).setOnClickListener(this);
_nbrPlace = (EditText)findViewById(R.id.id_nbrPlace);
_nbrPlace.setText("1", TextView.BufferType.EDITABLE);
_barCode = (EditText)findViewById(R.id.barCode);
Button buttonBarCode = (Button) findViewById(R.id.ButtonBarCode);
buttonBarCode.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.ButtonBarCode :
EditText barCode = (EditText)findViewById(R.id.barCode);
String str = barCode.getText().toString();
// Save and Reset to default code bar
String str = _barCode.getText().toString();
//_barCode.setText("", TextView.BufferType.EDITABLE);
if (str.isEmpty()) {
display(getString(R.string.empty_text_area), false);
}
else {
validateTicket(str);
}
break;
}
}
......@@ -68,11 +90,10 @@ public class Read_QR_Code extends ActionBarActivity implements View.OnClickListe
}
try {
Intent intent = new Intent(ACTION_SCAN);
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
startActivityForResult(intent, 1);
} catch (ActivityNotFoundException anfe) {
showDialog(Read_QR_Code.this, "Auncun lecteur de QRCode n'a été trouvé", "Télécharger" +
" un scanner ?", "Oui", "Non").show();
showDialog(Read_QR_Code.this, getString(R.string.noQRCodeApplication), getString(R
.string.downloadQRCode), "Oui", "Non").show();
}
}
......@@ -100,7 +121,7 @@ public class Read_QR_Code extends ActionBarActivity implements View.OnClickListe
}
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) if (resultCode == RESULT_OK) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
validateTicket(contents);
......@@ -108,23 +129,69 @@ public class Read_QR_Code extends ActionBarActivity implements View.OnClickListe
}
public void validateTicket(String result) {
String str[] = result.split(" ");
Boolean found = false;
final String str[] = result.split(" ");
int nbrPlaceSelect = Integer.parseInt(_nbrPlace.getText().toString());
int nbrPlaceTot = Integer.parseInt(str[2]);
Boolean idFound = false;
// Reset to default number of place
_nbrPlace.setText("1", TextView.BufferType.EDITABLE);
if (Integer.parseInt(str[2]) < nbrPlaceSelect) {
display(getString(R.string.nbPlaceOversize), false);
return;
}
Iterator<Key_List> itr = key_list.iterator();
while (itr.hasNext()) {
Key_List key = itr.next();
if (key.getId() == Integer.parseInt(str[1])) {
String hmac = hmacDigest(str[0] + " " + str[1] + " " + str[2], key.getKey(),
"HmacSHA1");
if(str[3].equals(hmac.substring(0, 8).toUpperCase())) {
display(getString(R.string.ebillet_true), true);
found = true;
// generate HMAC in hex
String hmac = hmacDigest(str[0]+" "+str[1]+" "+str[2], key.getKey(), "HmacSHA1");
if(str[3].equals(hmac.substring(0, str[3].length()).toUpperCase())) {
// Ticket is valid
idFound = true;
JSONObject jsonParams = new JSONObject();
StringEntity entity = null;
try {
// Set parameters in JSON structure
jsonParams.put("verif", str[3]);
jsonParams.put("nb", nbrPlaceSelect);
jsonParams.put("qt", nbrPlaceTot);
// Set JSON parameters for Post request
entity = new StringEntity(jsonParams.toString());
} catch (JSONException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Send Post Request
AsyncHttpClient client = new AsyncHttpClient();
client.post(this, server + "/validate", entity, "application/json",
new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
Log.i("debug", "toto ");
Log.i("debug", response.toString());
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
display(getString(R.string.serverError), false);
}
});
}
return;
}
}
if (!found) {
if (!idFound) {
display(getString(R.string.ebillet_false), false);
}
}
......@@ -150,30 +217,6 @@ public class Read_QR_Code extends ActionBarActivity implements View.OnClickListe
toast.show();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_read__qr__code, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
Intent intent = new Intent(Read_QR_Code.this, Settings.class);
if (key_list != null)
if (!key_list.isEmpty())
intent.putParcelableArrayListExtra("key_list", key_list);
startActivity(intent);
return true;
}
return super.onOptionsItemSelected(item);
}
public static String hmacDigest(String msg, String keyString, String algo) {
String digest = null;
try {
......
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/label_ipAddress"
android:id="@+id/textView"
android:textSize="18dp"/>
<Space
android:layout_width="120px"
android:layout_height="20px"
android:layout_alignTop="@+id/textView"
android:layout_toRightOf="@+id/textView"
android:id="@+id/space1"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_ipAddress"
android:hint="@string/label_ipAddress"
android:inputType="text"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_alignTop="@+id/textView"
android:textSize="18dp"
android:layout_toRightOf="@+id/space1"
android:visibility="visible"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/label_port"
android:id="@+id/textView2"
android:layout_below="@+id/text_ipAddress"
android:visibility="visible"/>
<Space
android:layout_width="20px"
android:layout_height="20px"
android:id="@+id/space2"
android:layout_alignTop="@+id/textView2"
android:layout_toRightOf="@+id/textView2"
android:visibility="invisible"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/text_port"
android:hint="@string/label_port"
android:layout_alignParentLeft="false"
android:layout_alignParentStart="false"
android:layout_alignTop="@+id/textView2"
android:layout_toRightOf="@+id/space2"
android:visibility="visible"
android:inputType="numberSigned"/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/validate"
android:id="@+id/button_ipAddress"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="false"
android:layout_below="@+id/text_port"/>
</RelativeLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical"
tools:context="com.javacodegeeks.androidstartactivityforresultexample.ActivityOne" >