美文网首页
捆绑 Django 和 Android 应用程序

捆绑 Django 和 Android 应用程序

作者: 蜗牛是不是牛 | 来源:发表于2022-07-27 16:21 被阅读0次

    您是否使用 Django 开发了 Web 应用程序并考虑将其扩展到 android 应用程序?

    那么你就在完美的地方。

    让我们开始吧!!

    我们的计划:

    1] 创建 Django Web 应用程序:我们将在 django Web 应用程序中创建基本的用户配置文件机制。

    2] 创建与 Android 通信的 API:我们将创建控制器(Django 视图),它将返回 JSON 响应(将充当 API),我们将在 android 应用程序中捕获它。

    3] 开发 Android 网络应用程序:我们将创建将与 Django API 通信的 android 网络应用程序。


    注意:- 您必须在线部署您的 Web 应用程序,以便该站点必须是公开可访问的(即它必须可以从其他设备访问)。

    现在让我们执行我们的计划:

    1] 在 Django 中开发基本的学生档案应用程序:

    • 首先通过在终端中输入以下命令来创建 Django 项目(basic_app):django-admin startproject basic_app

    • 在您的项目中创建新应用 StudentProfile:

       cd basic_app
       django manage.py startapp StudentProfile
       python manage.py createsuperuser 
    
    

    第一个命令会将终端带入当前项目目录。
    第二个命令用于创建 StudentProfile 应用程序。
    第三个命令为管理站点创建超级用户(管理员)。此命令要求输入用户名、电子邮件和密码。

    • 我们通过在 StudentProfile 和 User 之间提供一对一的关系来扩展基本的 User auth 模型来存储特定于学生的其他信息:
        #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)
    
    

    上面的代码进入 StudentProfile App 中的 models.py。

    • 从代码片段 1 开始,我们正在存储学生的个人资料图片,因此我们必须在设置中定义 MEDIA_URL 和 MEDIA_ROOT 以及提供静态文件的其他一些设置:
    #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/')
    
    

    同样在 settings.py 中的 TEMPLATE dict 的 DIRS 字段中添加路径:['assets/static/',]
    还在 INSTALLED_APPS 的 Django Settings.py 中添加“StudentProfile”,这有助于服务器检测项目中的新应用程序:

    INSTALLED_APPS=[ ...,
      ...,
      'StudentProfile',]
    
    
    • 在项目目录中创建文件夹 assets,在 assets 中创建 2 个文件夹 static 和 profilepic(static 将提供模板、css、js 和 profilepic 将存储学生的个人资料图片)。

    • 创建模型后,我们应该在管理站点中注册模型,以便我们可以从管理站点添加删除编辑模型实例:

    #CODE SNIPPET 3
    from .models import StudentProfile
    from django.contrib import admin
    
    admin.site.register(StudentProfile)
    
    
    • 现在我们将定义控制器(Django Views)用于如何呈现登录表单以及如何在成功登录后呈现学生信息(我们正在创建非常基本的表单,因为我们的主要目的是创建将与android通信的api):
    #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")
    
    

    此代码进入 StudentProfile 中的 views.py。

    说明:-
    1]登录:- 如果请求是 'GET',则此定义检查请求是 'POST' 还是 'GET',然后它将为 Signin.Else 呈现表单,如果请求是 'POST' 则它将使用从表单接收的数据并将尝试对用户进行身份验证。如果凭据正确,则用户已登录,否则将显示错误消息。

    2]显示:-一旦用户成功登录,他将被重定向到显示页面,该页面通过呈现html来显示他的信息。

    3]注销:-此定义将用户注销。


    注意:- 我们只需要更改我们的视图来创建用于与 android 应用程序通信的 API。

    • 现在我们将创建 Urls(路由器),它将我们路由到将为我们呈现页面的不同控制器:
    #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)
    
    

    此代码必须包含在 basic_app urls.py 文件中。

    说明:-
    1]urlpatterns 定义用于调用不同控制器的 url,这些控制器要么呈现要么重定向。
    2]include用于包含应用程序的所有url。
    3]我们正在为 MEDIA_ROOT ('assets/') 添加 urlpatterns URL 将是 MEDIA_URL ('/media/')。这将暴露项目目录中的媒体文件。

    #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 
    ]
    
    

    此代码必须包含在 StudentProfile 的 urls.py 中。

    • 现在我们需要创建将由视图呈现的模板:
    <!--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>
    
    

    此模板应作为 login.html 存储在 assets/static/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>
    
    

    此模板应作为 display.html 存储在 assets/static/html 中

    现在我们完成了我们的 Web 应用程序

    2] 为 Android 应用程序创建 API:-正如在其中一篇注释中所说,创建 API 非常容易。我们将使用与之前为 Web 应用程序创建的控制器相同的控制器,只是我们将进行一些小的更改。

    • 启动名为 api 的新项目:python manage.py startapp api
    • 表单和登录 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")
    
    

    这段代码应该放在文件 api/views.py

    解释:-

    1]登录:- 附加了 url '/api' 中有一些小的变化,这是因为现在我们指的是不同的控制器集,我们将使用这些控制器与应用程序进行通信。
    如果请求方法是“GET”,那么与我们在 Web 应用程序中的代码相比,代码会有重大变化。这是因为一旦我们登录到应用程序并且我们关闭应用程序而不注销它必须打开配置文件页面对我们来说,而不是一种形式。
    我们正在检查 request.session 是否存在,如果存在,那么我们将直接重定向到配置文件页面,如果不存在,那么我们将返回包含 csrf 令牌的表单(什么是 csrf 以及它是如何工作的,我们将在稍后讨论)。

    2]显示:-而不是呈现显示页面,我们只是将JSON作为HttpResponse返回给应用程序(即使控制器作为REST API工作)。我们使用django本身提供的序列化器库将django模型序列化为JSON,用于序列化模型。


    注意:-当请求方法是“GET”并且没有与请求关联的会话对象时,我们正在渲染名为 api_login_workThrough.html 的页面,这是我想到使用 django 的 csrf 机制与我的 android 一起工作的工作应用程序。可能有更好的方法,但我想出了这个简单的想法。我们将在本文后面详细了解这项工作的工作原理。

    • api_login_workThrough.html 位于 assets/static/html 并包含:-
    <form>{%csrf_token%}</form>
    
    
    • 现在我们将为 API 创建 URLS(Routers):
    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)
    ]
    
    

    此代码由 api/urls.py 包含。

    看起来和StudentProfile的urls.py一样,其实是一样的,区别在于basic_app的urls.py。

    在 basic_app(主项目应用程序)的 urls.py 中,在末尾添加 url 模式:-

    urlpatterns =[
                   ...,
                   ...,
                   path('api/',include('api')), ]
    
    

    我们为用户学生资料创建了 API。

    现在让我们开始使用 Android

    • Android 应用概览

    AsyncRequest:-请求响应处理程序

    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:-使用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 存储实现

    可以在以下位置找到实现:cookie 存储的 Gist Repo

    这个 git repo 包含来自我们应用程序的两个类,即。BasicCookieStore 和 SerializableHttpCookie,第二类支持第一类将 httpcookie 对象序列化为字符串并存储在 cookie 存储中。

    MainActivity:-提供用户登录的登录页面

    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>
    
    

    仪表板:-用户个人资料预览

    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>
    
    

    哦,就是这样。

    我们的教程已经完成。我只分享了对理解很重要的代码片段,其余的我都跳过了,因为文章的长度。我正在链接我的 web 应用程序仓库和 android 应用程序仓库:

    1. Web 应用程序仓库
    2. Android 应用程序仓库

    链接:https://dev.to/akshaychhajed1998/strapping-django--android-application-e57

    相关文章

      网友评论

          本文标题:捆绑 Django 和 Android 应用程序

          本文链接:https://www.haomeiwen.com/subject/qosxwrtx.html