Have you developed an web application using Django and Thinking of extending it to android application?
Then you are at perfect place.
Let's get Started!!
Our Plan:
1] Creating the Django Web Application: We will be creating basic user profile mechanism in django web application.
2] Creating API to Communicate with Android: We will be creating the Controllers(Django Views) which will return JSON response (will act as API) Which we will catch in android application.
3] Developing Android Networking Application: We will be creating android networking app which will be communicating with Django API's.
NOTE:- You must Deploy Your web application Online such that the site must be publically Accessible(i.e It must be accessible from other devices).
Now Let's Execute Our Plan:
1] Developing Basic Student Profile Application in Django:
Start by creating the Django Project(basic_app) by typing following command in to the terminal:
django-admin startproject basic_app
Create new app StudentProfile in your project:
cd basic_app
python manage.py startapp StudentProfile
python manage.py createsuperuser
1st command will take terminal into current project directory.
2nd command is used to create StudentProfile app.
3rd command creates superuser(admin) for admin site.This command ask for username,email and password.
- We are sort of extending basic User auth model to store the other information specific to student by providing one-to-one relation between StudentProfile and User:
#CODE SNIPPET 1
from django.db import models
#Create your models here.
from django.db import models
from django.contrib.auth.models import User
class StudentProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
student_id = models.CharField(max_length=7,null=False,unique=True,default='')
profile_pic = models.ImageField(upload_to='profilepic/',null=False,default='')
mobile_number=models.BigIntegerField(blank=True,default=9999999999)
def __str__(self):
return "{}".format(self.student_id)
The Above code goes in to models.py in StudentProfile App.
- As from code snippet 1 we are storing profile picture of the student so we must define MEDIA_URL & MEDIA_ROOT in settings & also some other settings for serving Static Files:
#CODE SNIPPET 2
#add this lines in settings.py
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
STATICFILES_DIRS = [os.path.join(BASE_DIR,'assets/static/'),'']
MEDIA_ROOT = os.path.join(BASE_DIR,'assets/')
Also in DIRS field in TEMPLATE dict in settings.py add path:['assets/static/',]
Also add 'StudentProfile' in Django Settings.py in INSTALLED_APPS at end this helps the server detecting new apps in project:
INSTALLED_APPS=[ ...,
...,
'StudentProfile',]
Create folder assets in project directory and inside assets create 2 folder static and profilepic (static will serve template,css,js & profilepic will store profile picture of student).
Once we have created model we should register the model in admin site so we can add remove edit the model instances from admin site:
#CODE SNIPPET 3
from .models import StudentProfile
from django.contrib import admin
admin.site.register(StudentProfile)
- Now we will define controller (Django Views) for how to render login form and how to render student information after successfull login(we are creating very basic form because our main purpose is to create api which will communicate with android):
#CODE SNIPPET 4
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import logout,login,authenticate
from .models import StudentProfile
from django.core import serializers
from django.contrib.auth.models import User
# Create your views here.
def Login(request):
if request.method == 'POST':
user=authenticate(request,username=request.POST.get('username'),password=request.POST.get('password'))
if user is not None:
login(request,user)
return redirect('/display')
else:
return HttpResponse("Credentials are Incorrect")
else:
return render(request,'html/login.html',{})
def display(request):
if request.method == 'GET':
user = User.objects.filter(pk = request.user.pk)[0]
profile = StudentProfile.objects.filter(user = request.user.pk)[0]
return render(request,'html/display.html',{'user':user,'profile':profile})
def Logout(request):
if request.user.is_authenticated:
logout(request)
return redirect('/')
else:
return HttpResponse("ERROR:Error Logging Out")
This code goes Into views.py in StudentProfile.
Explanation:-
1]Login:-this defination checks whether the request is 'POST' or 'GET' if It is 'GET', Then It will render the form for Signin.Else,if request is 'POST' then it will use data received from form and will try to authenticate user.If credentials are correct then user is LoggedIn else Error message is displayed.
2]display:- Once User is Successfully loggedin he is redirected to dispaly page which displays his information by rendering the html.
3]Logout:-This defination logs the user out.
NOTE:- We will just require to change our views to create the API's for communicating with android application.
- Now we will create Urls (Routers) which will route us to different controller which will render pages for us:
#CODE SNIPPET 5
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('StudentProfile.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
This code must be contained by basic_app urls.py file.
Explanation:-
1]urlpatterns define url for invoking different controllers which either renders or redirects.
2]include is used to include all urls of apps.
3]We are adding urlpatterns for MEDIA_ROOT ('assets/') URL will be MEDIA_URL ('/media/').This will expose Media files from project directory.
#CODE SNIPPET 6
from django.contrib import admin
from django.urls import path,include
from .views import Login,display,Logout
urlpatterns = [
path('',Login),#Calls Login View(Homepage)
path('display/',display),#Calls display View(After Successful Login )
path('logout/',Logout),#Controller for logging out
]
This code must be contained by StudentProfile's urls.py.
- Now we Need to Create Template's which will be render by Views:
<!--CODE SNIPPET 7-->
<!DOCTYPE html>
<html>
<head>
<title>LOGIN</title>
</head>
<body style="font-family:sans-serif;">
<form method='POST' action=''>
{%csrf_token%}
<input type='text' name='username' placeholder='username'>
<input type='password' name='password' placeholder='password'>
<button>SUBMIT</button>
</form>
</body>
</html>
This Templates should be stored in assets/static/html as login.html
<!--CODE SNIPPET 8-->
{% load static %}
<!DOCTYPE html>
<html>
<body>
<p>username:{{user.username}}</p>
<p>firstname:{{user.first_name}}</p>
<p>lastname:{{user.last_name}}</p>
<p>email:{{user.email}}</p>
<p>student_ID:{{profile.student_id}}</p>
<p>mobile number:{{profile.mobile_number}}</p>
<img src="/media/{{profile.profile_pic}}" height="25px" width="25px">
<form action='/logout' method='GET'><button>LOGOUT</button></form>
</body>
</html>
This Templates should be stored in assets/static/html as display.html
Now We are Done with our Web App
2] Creating API's for Android Application:-As in one of the Note, I told it's very easy to create the API's.We will use same controller as created before for web application just we will have some small changes.
- Start New Project Called api:
python manage.py startapp api
- Form & Login API:
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import logout,login,authenticate
from StudentProfile.models import StudentProfile
from django.core import serializers
from django.contrib.auth.models import User
from django.middleware.csrf import *
# Create your views here.
def Login(request):
if request.method == 'POST':
user=authenticate(request,username=request.POST.get('username'),password=request.POST.get('password'))
if user is not None:
login(request,user)
return redirect('/api/display/')
else:
return HttpResponse("ERROR:-Credentials are Incorrect")
else:
if request.session.is_empty():
return render(request,'html/api_login_workThrough.html',{})
authenticate(request)
print('-------------------')
print(request.user)
return redirect('/api/display/')
def display(request):
if request.method == 'GET':
user = User.objects.filter(pk = request.user.pk)[0]
profile = StudentProfile.objects.filter(user = request.user.pk)[0]
return HttpResponse(serializers.serialize('json',[user,profile]))
def Logout(request):
if request.user.is_authenticated:
logout(request)
return redirect('/')
else:
return HttpResponse("ERROR:-Error Logging Out")
This code should be placed in file api/views.py
Explanation:-
1]Login:-there are some minor changes in url '/api' is appended this is because now we are referring different set of controllers which we will use to communicate with application.
If the request method is 'GET' then there is significant changes in the code as compared to what we have in web app.This is because once we are logged in to the app and we close app with out logging out it must open profile page for us rither than a form.
we are checking request.session exist or not, If it exist then we will redirect to profile page directly and if it not then we will return the form containing csrf token(what is csrf and how it works we will discuss it later).
2]display:-rither than rendering the display page we are simply return JSON as HttpResponse to the apllication(i.e making controller work as REST API).we have serialize django model to JSON using serializers library provided by django itself for serializing models.
NOTE:-when request method is 'GET' and there is no session object associated with request we are rendering the page called api_login_workThrough.html,This was the work Through of which I thought of to use csrf mechanism of django to work with my android application.There may be better way,but I came up with this simple Idea.We will see how this work Through works in detail later in the article.
- The api_login_workThrough.html resides in assets/static/html and contains:-
<form>{%csrf_token%}</form>
- Now we will create URLS(Routers) for API:
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from .views import *
urlpatterns = [
path('login/',Login),
path('display/',display),
path('logout/',Logout)
]
This code is contain by api/urls.py.
It looks same as that of StudentProfile urls.py,Actually Its Same the difference will be made by urls.py of basic_app.
In urls.py of basic_app(Main project app) add url pattern at end:-
urlpatterns =[
...,
...,
path('api/',include('api')), ]
We Created API for the User Student Profile.
Now Let's get Started with Android
- OverView of Android Apllication
AsyncRequest:-Request Response Handler
package com.example.workstation.basic;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;
public class AsyncRequest extends Thread
/* Thread is used to make the request response cycle asynchronous to help preventing the UI from being Unresponsive*/
{
final String TAG = AsyncRequest.class.getSimpleName();
final String domain_name;
BasicCookieStore store;
/*Basic Cookie Store is Persistent Cookie Store implementation for Android used to store Cookie */
String ResponseMsg = new String(); //Response message received from (Django)server
int ResponseCode; //Response code received from server (Code: (2xx for OK),(3xx for Redirects),(4xx for ClientError),(5xx for InternalSerer Error)
String ResponseBody = new String(); //It is Data Received from Server(HTTP response or File response or JSON response)
Map<String,List<String>> ResponseHeader;//Response Header Received from Server
String Url = new String(); //Url to which to send request and response
String RequestBody = new String(); //Request Body means Data to be sent to Server
final String RequestType; //Type of Request(GET,POST)
AsyncRequest(String requestType,Context context)
/* Context is accepted for CookieStore to initialize for the Application*/
{
RequestType = requestType;
store=new BasicCookieStore(context);
domain_name=context.getResources().getString(R.string.domain_name);
}
@TargetApi(Build.VERSION_CODES.N)
@Override
public void run()
{
try
{
URL url = new URL(Url);
URI uri = new URI(Url);
HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
/*HttpURLConnection is the class which establish the connection between client and server and exchange data
* using HTTP request response cycle.
* url.openConnection() establishes the connection between client and server */
httpconn.setInstanceFollowRedirects(false);
/*Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this HttpURLConnection
instance*/
HttpsURLConnection.setFollowRedirects(false);
/*Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this class*/
httpconn.setRequestMethod(RequestType);//set Types of Request
String S="";
for(HttpCookie H:store.get(new URI(domain_name)))
S+=H+"; ";
httpconn.setRequestProperty("Cookie",S);
/*retriving the cookie from cookie store and sending back to the server(session_id,csrf_token,etc)*/
if(RequestType=="POST")
{
DataOutputStream output=new DataOutputStream(httpconn.getOutputStream());
output.writeBytes(RequestBody);
output.flush();
output.close();
}
/* if the request is POST then we send data to the server this using output stream received from connection*/
boolean redirect = false;
// normally, 3xx is redirect
int status = httpconn.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) { //if request succeds then skip
if (status == HttpURLConnection.HTTP_MOVED_TEMP
|| status == HttpURLConnection.HTTP_MOVED_PERM
|| status == HttpURLConnection.HTTP_SEE_OTHER)//if response code is 3xx then it is redirect request
redirect = true; //set redirect to true
}
System.out.println("Response Code ... " + status);
if(redirect) {
// when response code 3xx then we receive redirect url in header field called "location"
String newUrl = httpconn.getHeaderField("Location");
// get the cookie if need, for login
List<String> cookiesL =httpconn.getHeaderFields().get("set-cookie");
Log.i(TAG, "run: "+httpconn.getHeaderFields());
if(cookiesL != null)
for(String x:cookiesL)
store.add(new URI(domain_name),HttpCookie.parse(x).get(0));
// open the new connnection again on url recived from location header
url = new URL(domain_name+newUrl);
uri = new URI(domain_name+newUrl);
Log.i(TAG, "run: "+url);
httpconn.disconnect();
httpconn = (HttpURLConnection) url.openConnection();
httpconn.setInstanceFollowRedirects(false);
HttpURLConnection.setFollowRedirects(false);
httpconn.setRequestMethod("GET"); //considered that redirect url will be GET request only
S="";
for(HttpCookie H:store.get(new URI(domain_name)))
S+=H+"; ";
httpconn.setRequestProperty("Cookie",S);
Log.i(TAG, "CookiesSession--: "+S);
/*same as processed for first request*/
}
Log.i(TAG, "run: " + httpconn);
this.ResponseMsg = httpconn.getResponseMessage(); //retriving response message from httpconn object
this.ResponseCode = httpconn.getResponseCode();//response code is retrived
this.ResponseHeader = httpconn.getHeaderFields(); //getting header fields
byte[] b = new byte[1024 * 1024]; // reserving the memory for responsebody
int len;
len = (new DataInputStream(httpconn.getInputStream())).read(b); //reads complete response body from httpconn object
Log.i(TAG, "run: "+b.toString());
this.ResponseBody = new String(b, 0, len); //stores in responsebody
httpconn.disconnect();
}
catch(IOException e)
{
Log.e(TAG, "run: ",e );
}
catch (URISyntaxException e)
{
Log.e(TAG, "run: ",e );
}
}
/*Getters and Setters*/
void setUrl(String Url)
{
this.Url=Url;
}
void setRequestBody(String RequestBody)
{
this.RequestBody=RequestBody;
}
String getResponseMsg()
{
return ResponseMsg;
}
String getResponseBody()
{
return ResponseBody;
}
Map<String,List<String>> getResponseHeader()
{
return ResponseHeader;
}
}
BitmapD:-Loads the image asynchronously using url
package com.example.workstation.basic;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class BitmapD extends Thread {
Bitmap B;
String Url;
public void setUrl(String Url)
{
this.Url=Url;
} //Url from which to fetch image
public void run()
{
try {
Log.e("src",Url);
URL url = new URL(Url); // converts string url to URL object
HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //establishes connection between client and server
connection.setDoInput(true);
connection.connect();//connection is established
InputStream input = connection.getInputStream();//retriving input stream to retrive image data
B= BitmapFactory.decodeStream(input);//convert input received to proper image format depending on header
Log.e("Bitmap","returned");
} catch (IOException e) {
e.printStackTrace();
Log.e("Exception",e.getMessage());
}
}
public Bitmap getBitmap()
{
return B;
}//getter for fetching bitmap
}
BasicCookieStore:-Persistent Cookie store implementation
The Implementation can be found at:Gist Repo for cookie store
This git repo contains two classes from our application viz. BasicCookieStore and SeriallizableHttpCookie,2nd class supports the first class to serialize the httpcookie object to string and store in the cookie store.
MainActivity:-Provides the Login Page for User Login
package com.example.workstation.basic;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
public class MainActivity extends AppCompatActivity {
String domain_name;
BasicCookieStore store;
String csrf_token=new String();
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
domain_name=getResources().getString(R.string.domain_name); //server domain
store = new BasicCookieStore(this); //Creating CookieStore for Application
AsyncRequest P=new AsyncRequest("GET",this); //AsyncRequest object to snrd request
P.setUrl(domain_name+this.getResources().getString(R.string.Login)); //url to which to send request
P.start(); //starting asynchronous process
try
{
P.join(); //procced after process P is completed
}
catch (InterruptedException e)
{
e.printStackTrace();
}
Log.i("FORM:---", "onCreate: "+P.getResponseBody());
/*remember of csrf work through i told of explaining in android
once we receive the workthrough file from server we are checking for substring at index 1 to 4 if it is word "form"
then we are retriving the csrf token from form generated by {%csrf_token%} tag in template and store it in a variable
In response header there is field called "set-cookie" which contains cookie to be set we retrive the data and store it in this store
*/
if(P.getResponseBody().substring(1,5).equals("form"))
{
csrf_token = P.getResponseBody().substring(61, 61 + 64);
Log.i("csrf_token:--", "onCreate: "+csrf_token);
try {
store.add(new URI(domain_name), HttpCookie.parse(P.getResponseHeader().get("set-cookie").get(0)).get(0));
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
/*then we check if it returns error substring if so then something has went wrong and we recreate the activity
else
if workthrough form and also error is not returned then it implies that the user session was saved in cookie store and hence we directly authenticate
user to the user data preview
*/
else
{
if(P.getResponseBody().substring(0,5).equals("Error"))
{
this.recreate();
}
else
{
Intent dashBoard = new Intent(this,DashBoard.class); //Explicit intent creation
this.finish();
dashBoard.putExtra("displayData",P.getResponseBody());//sending response data to new intent i.e dashboard
Log.i("JSON:::", "onCreate: "+P.getResponseBody());
store.loadAllCookies();
Log.i("VC", "SignIN: "+store.getCookies());
startActivity(dashBoard);//starting the intent(control goes to dashboard activity)
}
}
}
// create an action bar button
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return super.onCreateOptionsMenu(menu);
}
/* this is function which is triggered when user click on login button*/
void SignIN(View B) throws MalformedURLException, URISyntaxException, InterruptedException {
Button b = (Button)B;
EditText usernameView = (EditText) findViewById(R.id.Email);
EditText passwordView = (EditText) findViewById(R.id.Password);
String username = usernameView.getText().toString(); //retriving username from username field
String password = passwordView.getText().toString(); //retriving password from password field
if(!username.isEmpty() && !password.isEmpty()) //username and password validations
{
b.setClickable(false);
AsyncRequest P = new AsyncRequest("POST",this); //creating the login request
P.setUrl(domain_name+this.getResources().getString(R.string.Login));//setting login url
P.setRequestBody("username="+username+"&password="+password+"&csrfmiddlewaretoken="+csrf_token+"&LOGIN=LOGIN");
//setting request body it contains(username,password and csrf token which is used for CSRF attack protection by django)
P.start();//satrting the process
P.join();//procced after process P is completed
if(P.getResponseBody().substring(0,5).equals("ERROR"))//if response contains "ERROR" string then recreate activity
{
Toast.makeText(this,P.getResponseBody(),Toast.LENGTH_LONG).show();
usernameView.setText("");
passwordView.setText("");
this.recreate();
}
else //if login is successful then create Dashboard activity
{
Intent dashBoard = new Intent(this,DashBoard.class);
dashBoard.putExtra("displayData",P.getResponseBody());
store.loadAllCookies();
this.finish();
startActivity(dashBoard);
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:background="@color/colorPrimaryDark">
<TextView
android:id="@+id/LOGIN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/Email"
android:text="LOGIN"
android:textColor="@color/green_intheme"
android:layout_centerHorizontal="true"
android:layout_marginBottom="15dp"
android:fontFamily="serif-monospace"
android:textSize="35dp"/>
<EditText
android:id="@+id/Email"
android:layout_width="match_parent"
android:layout_height="30dp"
android:inputType="textWebEmailAddress"
android:layout_centerVertical="true"
android:layout_above="@id/Password"
android:background="@color/gray_outlook"
android:layout_marginBottom="10dp"
android:hint="Email"/>
<EditText
android:id="@+id/Password"
android:layout_width="match_parent"
android:layout_height="30dp"
android:inputType="textWebPassword"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:background="@color/gray_outlook"
android:hint="Password"/>
<Button
android:id="@+id/SignIN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sign IN"
android:layout_marginTop="10dp"
android:layout_below="@id/Password"
android:background="@color/blue_intheme"
android:layout_centerHorizontal="true"
android:textSize="20dp"
android:onClick="SignIN"
android:clickable="true"/>
</RelativeLayout>
DashBoard:-user profile preview
package com.example.workstation.basic;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class DashBoard extends AppCompatActivity {
boolean flag=true;
String domain_name;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dash_board);
this.domain_name =this.getResources().getString(R.string.domain_name);
BitmapD B=new BitmapD();
Intent DataIntent = getIntent(); //receiving the intent
JSONArray obj = new JSONArray();
try {
obj = new JSONArray(DataIntent.getStringExtra("displayData"));
//the received response from server was JSON serialized coverting it back to JSON Array
} catch (JSONException e) {
e.printStackTrace();
}
try {
Log.i("Json", "SignIN: "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("username"));
} catch (JSONException e) {
e.printStackTrace();
}
//selectiong differnt elements from UI(xml)
TextView username = (TextView) findViewById(R.id.username);
TextView firstname = (TextView) findViewById(R.id.firstname);
TextView lastname = (TextView) findViewById(R.id.lastname);
TextView email = (TextView) findViewById(R.id.email);
ImageView I =(ImageView) findViewById(R.id.ProfilePic);
try
{
//setting appropiate value from JSON Array
username.setText("username : "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("username"));
lastname.setText(""+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("last_name"));
firstname.setText(""+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("first_name"));
email.setText("Email : "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("email"));
B.setUrl(domain_name+"/media/"+((JSONObject)((JSONObject)obj.get(1)).get("fields")).get("profile_pic"));
//setting image url to BitmapD object which loads the image on other thread
B.start();
B.join();
Bitmap bm=B.getBitmap();
I.setImageBitmap(bm);
} catch (JSONException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.actionbardb, menu);
return super.onCreateOptionsMenu(menu);
}
//triggers on clicking close icon and finishes activity
public void Close(MenuItem i)
{
this.finish();
}
//triggers on clicking logout icon and destroys the current session and finishes activity
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void LogOut(MenuItem i) throws InterruptedException {
AsyncRequest P=new AsyncRequest("GET",this);
P.setUrl(domain_name+this.getResources().getString(R.string.Logout)); //sends logout request
P.start();
P.join();
this.finish();
}
}
<?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"
tools:context=".DashBoard">
<LinearLayout
android:id="@+id/DataLayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:background="@color/colorPrimaryDark"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="160dp"
android:layout_height="160dp"
card_view:cardCornerRadius="80dp"
card_view:cardBackgroundColor="@color/white"
card_view:cardElevation="20dp">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_margin="5dp"
card_view:cardCornerRadius="75dp"
card_view:cardBackgroundColor="@color/white"
card_view:cardElevation="10dp">
<ImageView
android:id="@+id/ProfilePic"
android:layout_width="150dp"
android:layout_height="150dp"/>
</android.support.v7.widget.CardView>
</android.support.v7.widget.CardView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/firstname"
android:layout_width="match_parent"
android:layout_height="30sp"
android:textSize="25sp"
android:fontFamily="serif-monospace"
android:textColor="@color/white" />
<TextView
android:layout_width="match_parent"
android:layout_margin="1dp"
android:layout_height="1dp"
android:background="@color/blue"/>
<TextView
android:id="@+id/lastname"
android:layout_width="match_parent"
android:layout_height="30sp"
android:textSize="25sp"
android:fontFamily="serif-monospace"
android:textColor="@color/white" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_margin="1dp"
android:layout_height="1dp"
android:background="@color/blue"/>
<TextView
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="30sp"
android:textSize="25sp"
android:fontFamily="serif-monospace"
android:textColor="@color/white" />
<TextView
android:layout_width="match_parent"
android:layout_margin="1dp"
android:layout_height="1dp"
android:background="@color/blue"/>
<TextView
android:id="@+id/email"
android:layout_width="match_parent"
android:layout_height="60sp"
android:textSize="25sp"
android:fontFamily="serif-monospace"
android:textColor="@color/white"/>
<TextView
android:layout_width="match_parent"
android:layout_margin="1dp"
android:layout_height="1dp"
android:background="@color/blue"/>
</LinearLayout>
</RelativeLayout>
Phew!!!
OHH ,That's It.
we are done with our Tutorial.I have shared only code snippet which are important for understanding ,rest all I have skipped because of the length of the Article.I am linking my web application repo and android application repo:
Top comments (6)
Hello, I am working on both Django and Android Studio. Your article is awesome. I would suggest you one edit in your article:
replace
django manage.py startapp StudentProfile
with
python manage.py startapp StudentProfile
Because manage.py will be interpreted by python interpreter only.
Thank You!
Hey, I was working on learning android studio, I have some experience with Django, your article looks helpful. I just have some problem setting it up can you help me out?
Yes, offcourse 🙂😀
Can you describe problem
Nice
Did it work for you? Could you set it up? I need help setting it up.