Smarthome App #2: Login-Bildschirm

Smarthome App, Tutorial
Teile diesen Beitrag

Im letzten Teil des Tutorials habe ich dir erklärt, wie du in Android Studio ein Projekt erstellen und die ersten Aufgaben erledigen kannst. Im heutigen Tutorial wird der Login-Bildschirm der App designed und implementiert. Dazu startest du, falls nicht bereits geschehen, Android Studio und öffnest das Projekt über “File -> Open…” bzw. “File -> Open Recent”.

Dieses Tutorial gibt es auch als Video!

Den Login-Bildschirm designen

Als erstes wird das Layout des Login-Bildschirms definiert. Dazu wird die Datei mobile -> res -> layout -> activity_login.xml geöffnet und der Code mit folgendem Code ersetzt (wenn die Datei geöffnet ist, kannst du links unten zwischen Design- und Textansicht umschalten):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="de.smarthome_blogger.smarthome.LoginActivity"
android:background="@color/layoutBackground"
android:id="@+id/frame">
 
	<android.support.v7.widget.CardView
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_centerVertical="true"
	android:layout_margin="15dp"
	app:cardElevation="@dimen/cardViewElevation"
	app:cardCornerRadius="@dimen/cardViewCornerRadius"
	app:cardUseCompatPadding="true">
 
		<LinearLayout
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:orientation="vertical"
		android:padding="5dp">
		
			<ImageView
			android:layout_width="match_parent"
			android:layout_height="120dp"
			android:id="@+id/app_logo"
			android:layout_margin="10dp"
			android:src="@mipmap/ic_launcher"/>
			
			<EditText
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:inputType="textPersonName"
			android:hint="Nutzername"
			android:layout_marginBottom="5dp"
			android:id="@+id/username"/>
			
			<EditText
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:inputType="textPassword"
			android:hint="Passwort"
			android:layout_marginBottom="5dp"
			android:id="@+id/password"/>
			
			<EditText
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:inputType="textUri"
			android:hint="Server-IP"
			android:layout_marginBottom="5dp"
			android:id="@+id/server_ip"/>
			
			<CheckBox
			android:layout_width="match_parent"
			android:layout_height="wrap_content"
			android:text="Login-Daten speichern"
			android:id="@+id/save_login"
			android:gravity="center_horizontal|center_vertical"
			android:layout_marginBottom="5dp"
			android:checked="false"/>
			
			<RelativeLayout
			android:layout_width="match_parent"
			android:layout_height="wrap_content">
			
				<Button
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				style="@style/Widget.AppCompat.Button.Colored"
				android:background="@color/colorPrimary"
				android:textColor="@color/textColorLight"
				android:text="Login"
				android:layout_alignParentRight="true"
				android:id="@+id/login_button"/>
			
				<ProgressBar
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:indeterminate="true"
				android:layout_centerInParent="true"
				android:visibility="gone"
				android:id="@+id/loading_animation"/>
			
			</RelativeLayout>
		
		</LinearLayout>
	
	</android.support.v7.widget.CardView>
 
</RelativeLayout>

Du kannst dir ansehen, wie das Design momentan aussieht, indem du links unten den Design-Tab anklickst. Das Design sollte nun in etwa so aussehen, wie im folgenden Bild:

So sollte der Login-Bildschirm jetzt aussehen.

So sollte der Login-Bildschirm jetzt aussehen.

LoginActivity implementieren

Nachdem das Design des Login-Bildschirms definiert worden ist, wird als nächstes die Funktionalität implementiert. Öffne dazu die Datei mobile -> java -> de.smarthome_blogger.smarthome -> LoginActivity.java und füge über der Methode “protected void onCreate(Bundle savedInstanceState)” folgende Variablen ein:

private EditText usernameField, passwordField, serverIpField;
private Button loginButton;
private CheckBox saveLogin;
private View loadingAnimation;

Diese Variablen sind die Textfelder, Buttons und die Checkbox des Login-Bildschirms.

In der Methode “protected void onCreate()” fügst du anschließend unter der Zeile “setContentView(R.layout.activity_login);” den folgenden Code ein:

//Actionbar verstecken
getSupportActionBar().hide();
 
//Views deklarieren
usernameField = (EditText) findViewById(R.id.username);
passwordField = (EditText) findViewById(R.id.password);
serverIpField = (EditText) findViewById(R.id.server_ip);
 
loadingAnimation = findViewById(R.id.loading_animation);
 
loginButton = (Button) findViewById(R.id.login_button);
 
saveLogin = (CheckBox) findViewById(R.id.save_login);
 
//Dem Button eine Aktion zuweisen
loginButton.setOnClickListener(new View.OnClickListener() {
	@Override
	public void onClick(View v) {
		String username = usernameField.getText().toString();
		String password = passwordField.getText().toString();
		String serverIp = serverIpField.getText().toString();
 
		//Eingaben auf Vollständigkeit prüfen
		if(username.equals("")){
			fehlermeldung("Bitte gib deinen Nutzernamen ein");
		}
		else if(password.equals("")){
			fehlermeldung("Bitte gib dein Passwort ein");
		}
		else if(serverIp.equals("")){
			fehlermeldung("Bitte gib die Adresse des Servers ein");
		}
		else{
			SaveData.setSaveLoginData(getApplicationContext(), saveLogin.isChecked());
 
			login(username, password, serverIp);
		}
	}
});
 
//Haken je nach gespeicherten Daten setzen oder nicht
saveLogin.setChecked(SaveData.getSaveLoginData(getApplicationContext()));
 
//Bei jeder Änderung neu speichren, ob Login-Daten gespeichert werden sollen
saveLogin.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {	
	@Override
	public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
		SaveData.setSaveLoginData(getApplicationContext(), isChecked);
	}
});
 
//Wenn Nutzerdaten vorhanden: automatisch einloggen
if(SaveData.getSaveLoginData(getApplicationContext())){
	String username = SaveData.getUsername(getApplicationContext());
	String password = SaveData.getPassword(getApplicationContext());
	String serverIp = SaveData.getServerIp(getApplicationContext());
 
	if(username != null && password != null && serverIp != null){
		//Textfelder mit gespeicherten Daten füllen
		usernameField.setText(username);
		passwordField.setText(password);
		serverIpField.setText(serverIp);
 
		saveLogin.setChecked(true);
 
		login(username, password, serverIp);
	}
}

Erklärung des Codes

Als erstes wird die sogenannte Actionbar (die Titelleiste der App) im Login-Bildschirm ausgeblendet. die UI-Komponenten initialisiert und ihnen die entsprechenden Funktionen (OnClickListener, OnCheckedChangeListener) zugewiesen. Als letztes wird mit einer if-Abfrage geprüft, ob Nutzerdaten vorhanden sind und ob beim letzten Login angegeben wurde, dass sich die App automatisch einloggen soll. Ist dies der Fall, versucht die App, sich mit den vorhandenen Nutzerdaten einzuloggen.

Als nächstes fügst du einfach den folgenden Code unter der Methode “onCreate()” ein:

/**
* Versucht den Nutzer einzuloggen
* @param username
* @param password
* @param serverIp
*/
public void login(final String username, final String password, final String serverIp){
	loadingAnimation.setVisibility(View.VISIBLE);
	
	Map<String, String> requestData = new HashMap<>();
	requestData.put("action", "getrooms");
	requestData.put("username", username);
	requestData.put("password", password);
	
	HTTPRequest.sendRequest(getApplicationContext(), requestData, serverIp, new HTTPRequest.HTTPRequestCallback() {
		@Override
		public void onRequestResult(String result) {
			loadingAnimation.setVisibility(View.GONE);
			
			if(result.equals("wrongdata")){
				fehlermeldung("Anmeldung nicht möglich! Bitte überprüfe deine Eingaben");
			}
			else if(result.equals("unknownuser")){
				fehlermeldung("Dieser Nutzer existiert nicht");
			}
			else{
				//gegebenenfalls Login-Daten speichern
				if(saveLogin.isChecked()){
				SaveData.setLoginData(getApplicationContext(), username, password);
				SaveData.setServerIp(getApplicationContext(), serverIp);
			}
			
			Intent intent = new Intent(LoginActivity.this, MainActivity.class);
			intent.putExtra(MainActivity.EXTRA_ROOMS, result);
			startActivity(intent);
			}
		}
		
		@Override
		public void onError(String msg) {
			loadingAnimation.setVisibility(View.GONE);
			fehlermeldung(msg);
		}
	});
}
 
/**
* Zeigt die übergebene Nachricht an
* @param msg
*/
public void fehlermeldung(String msg){
	Snackbar.make(findViewById(R.id.frame), msg, Snackbar.LENGTH_SHORT).show();
}

Erklärung des Codes

Die Methode “login()” versucht, sich mit den angegebenen Nutzerdaten auf dem Server einzuloggen. Bei Erfolg wird zur Main-Actvity (sozusagen das Hauptmenü der App) gewechselt und die zurückgegebenen Daten des Servers (in diesem Fall eine Liste der vorhandenen Räume, damit die Menüpunkte im Hauptmenü erstellt werden können) an die Main-Activity übergeben. Bei Scheitern der Verbindung wird eine Fehlermeldung ausgegeben.
Die Methode “fehlermeldung()” gibt lediglich den übergebenen Text aus.

SaveData anlegen & vorläufig implementieren

Nun muss noch die Klasse SaveData angelegt werden. Dazu klickst du mit der rechten Maustaste auf den Ordner “de.smarthome_blogger.smarthome” oder eine darin enthaltene Klasse und wählst “New -> Java class”. Dort gibst du nun als Namen “SaveData” ein. Alles andere lässt du unverändert und klickst “Ok”.

So legst du eine neue Klasse an.

So legst du eine neue Klasse an.

Jetzt öffnet sich die Klasse und du kannst sie bearbeiten. Vorerst werden nur Platzhalter-Methoden definiert, die beispielsweise vordefinierte Nutzerdaten zurückgeben. Diese Nutzerdaten solltest du noch entsprechend anpassen, indem du den Rückgabewert der Methode “getServerIp” auf die IP-Adresse deines Raspberry und den Nutzernamen und das Passwort in den Methoden “getUsername” und “getPassword” änderst.
Den folgenden Code fügst du nun in die Klasse SaveData ein (unter der Zeile “public class SaveData{“):

public static String getUsername(Context context){
	return "Testnutzer";
}
 
public static String getPassword(Context context){
	return "password";
}
 
public static String getServerIp(Context context){
	return "192.168.178.xyz";
}
 
public static void setLoginData(Context context, String username, String password){}
 
public static void setServerIp(Context context, String serverIp){}
 
public static void setSaveLoginData(Context context, boolean saveLogin){}
 
public static boolean getSaveLoginData(Context context){
	return true;
}

Der Login-Bildschirm ist vorerst fertig, das Design wird jedoch eventuell noch etwas überarbeitet. Im nächsten Teil der Tutorials kann dann mit dem Hauptmenü der APP begonnen werden.

Falls du Fragen oder Probleme hast, kannst du mir gerne einen Kommentar hinterlassen.

Teile diesen Beitrag
, , , ,
Vorheriger Beitrag
Smarthome App #1: Projekt erstellen & erste Schritte
Nächster Beitrag
Archivierte Sensorwerte abfragen

Ähnliche Beiträge

Menü