Skip to content
NULLFLAG Support
  • Products
      • Junior Mobile Security Engineer
        Able to interpret data exchanges in unencrypted apps and gain limited proficiency in common programming languages.
      View Pricing
      • Intermediate Mobile Analyst
        Proficient in advanced tool utilization, capable of bypassing anti-debugging protections and developing custom scripts via tool APIs to enhance analytical efficiency.
      Research Tiers
      Junior VS Intermediate Analyst Comparison
    • Advanced Security ResearcherCapable of enhancing core modules in open-source reversing tools and implementing kernel-level bypasses for advanced verification mechanisms.
    • View Advanced Analyst
    • Premium LMS Add-onsEnhance your courses with extra features. Gather insights, reward learners, protect your course content, and more!
    • Explore Thematic Courses
      NullFlag mobile App
  • Pricing
  • Specialties & Utilities
      Featured Topics
      • Native Hook
        Fix the structure and function table of C++
      • Kernel Hook
        Develop based on the kernel hook framework.
      • Memory CRC
        Memory checksum verification bypass and anti-cracking
      • IDA Pro Plugins
        Trace the execution flow of function assembly instructions
      • Frida Stalker
        Trace the execution flow of function assembly instructions
      • eBPF Development
        Kernel-level low-layer monitoring
      • All NullFlag Specialties
      Reverse Engineering Toolkit
      • gojue eCapture
        capture SSL/TLS text content without a CA.
      • stackplz Plus
        eBPF-based stack tracing tool on android.
      • FRIDA-DEXDump
        A frida tool to find and dump dex in memory.
      • deReferencing plugin
        IDA plugin implements new registers and stack views.
      • All intergrations
      BUNDLES
      • Hex-Ray Usage we’ll explore the essentials of IDA capabilities to kickstart your journey and disassemble your first binary file
      • See User Guide
      • MORE
      • Hex-Ray Release Notes
      • C++ SDK
      • IDAPython SDK
  • Resources
      • NullFlag Academy
        Videos, books, and resources to help you master tips.
      • Blog
        Blog articles with the latest news and tips.
      • Knowledge Base
        A support network to help you make the most to Base.
      • Frida Release Notes
        You can promptly receive updates on our latest news.
      • Get Help
        There is include our all help documents , you can find you needed content by searching.
      Professional Service
    • Problem Assistance and Tutoring ServicesIf you encounter difficult issues, you can submit your questions to us. We will respond within a guaranteed timeframe .
    • Other Resources
    • Join Our CommunityBecome a member of our online communication group to receive instant notifications and get timely solutions to your questions.
    • Join us on Discord!
  • instructor
  • [username]
    • My Profile
    • Courses
    • Log In / Registration
NULLFLAG Support
  • about
  • blog
  • contact

Android Example

  • Simple Android App Networking Request
View Categories
  • Home
  • Docs
  • evelopment and utilization, and solidification of hooks
  • Android Example
  • Simple Android App Networking Request

Simple Android App Networking Request

< 1 min read

0:00 / 1:04
  • View as Markdown Open this page as plain Markdown (opens in a new tab)
  • Open in ChatGPT Ask questions about this page (opens in a new tab)
  • Open in Claude Ask questions about this page (opens in a new tab)
  • Open in Google AI Studio Ask questions about this page (Google account required) (opens in a new tab)

Quickly develop an Android page (user login & jump)

  • Android UI and background logic
  • Network requests
  • Serialization and deserialization
  • Save XML file (cookie)

Android UI and background logic #

android UI #

User Login Interface #

📄
fragment_login.xml
Copy
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:app="http://schemas.android.com/apk/res-auto" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:padding="16dp"> 

<!-- Left and right borders for centered layout --> 
<androidx.constraintlayout.widget.Guideline 
android:id="@+id/guideline_start" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:orientation="vertical" 
app:layout_constraintGuide_percent="0.1" /> <androidx.constraintlayout.widget.Guideline 
android:id="@+id/guideline_end" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:orientation="vertical" 
app:layout_constraintGuide_percent="0.9" /> 

<!-- Username input box --> 
<com.google.android.material.textfield.TextInputLayout 
android:id="@+id/usernameTextInputLayout" 
android:layout_width="0dp" 
android:layout_height="wrap_content" 
android:hint="username" 
app:layout_constraintTop_toTopOf="parent" 
app:layout_constraintStart_toStartOf="@id/guideline_start" 
app:layout_constraintEnd_toEndOf="@id/guideline_end" android:layout_marginTop="100dp"> 

<com.google.android.material.textfield.TextInputEditText 
android:id="@+id/username" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:inputType="textEmailAddress"/> 
</com.google.android.material.textfield.TextInputLayout> 

<!-- Password input box --> 
<com.google.android.material.textfield.TextInputLayout 
android:id="@+id/passwordTextInputLayout" 
android:layout_width="0dp" 
android:layout_height="wrap_content" 
android:hint="password" 
app:passwordToggleEnabled="true" 
app:endIconMode="password_toggle" app:layout_constraintTop_toBottomOf="@id/usernameTextInputLayout" 
app:layout_constraintStart_toStartOf="@id/guideline_start" 
app:layout_constraintEnd_toEndOf="@id/guideline_end" 
android:layout_marginTop="16dp"> 

<com.google.android.material.textfield.TextInputEditText 
android:id="@+id/password" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:inputType="textPassword"/> 
</com.google.android.material.textfield.TextInputLayout> 

<!-- Login button --> 
<Button 
android:id="@+id/buttonLogin" 
android:layout_width="0dp" 
android:layout_height="wrap_content" android:text="Login" 
app:layout_constraintTop_toBottomOf="@id/passwordTextInputLayout" 
app:layout_constraintStart_toStartOf="@id/guideline_start" 
app:layout_constraintEnd_toEndOf="@id/guideline_end" 
android:layout_marginTop="24dp" /> 

<!-- Loading progress bar --> 
<ProgressBar 
android:id="@+id/loading" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:visibility="gone" 
app:layout_constraintTop_toBottomOf="@id/buttonLogin" 
app:layout_constraintStart_toStartOf="parent" 
app:layout_constraintEnd_toEndOf="parent" 
android:layout_marginTop="16dp" </androidx.constraintlayout.widget.ConstraintLayout>

Function Interface #

📄
fragment_fn1.xml
Copy
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Fn1Fragment">

    <LinearLayout
        android:orientation="vertical"
        android:padding="16dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/hello_blank_fragment"
            android:textSize="18sp"
            android:paddingBottom="16dp" />

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/usernameTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter_password_usernameTextInputLayout">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/editTextUsername"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textMultiLine"
                android:maxLines="5"
                android:minLines="1"
                android:scrollHorizontally="false"
                android:gravity="start|top"/>
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/passwordTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:hint="Display_password_text_passwordEditText"
            app:passwordToggleEnabled="true">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/passwordEditTextFn1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textPassword|textMultiLine"
                android:maxLines="5"
                android:minLines="1"
                android:gravity="start|top"/>
        </com.google.android.material.textfield.TextInputLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp">

            <Button
                android:id="@+id/buttonFn2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="clang_Call_Java_Static(v8)_button_Fn2" />

            <Button
                android:id="@+id/buttonRun1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="jniCall_static()_button_Run1" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="20dp">

            <Button
                android:id="@+id/buttonFn3"
                android:layout_width="0dp"
                android:layout_height="112dp"
                android:layout_weight="1"
                android:text="clang_Call_Java_NewInstantiated_Object_(v9)_button_Fn3" />

            <Button
                android:id="@+id/buttonRun2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="jNI_Dynamic_Register()_button_Run2" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginTop="60dp">
            <Button
                android:id="@+id/buttonFn1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="jniCall()_button_Fn1" />
            <Button
                android:id="@+id/buttonRun3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Calculate_Ciphertext_(Result_v3)_button_Run3" />


        </LinearLayout>

    </LinearLayout>
</ScrollView>

Function Button Background Logic #

☕
Fn1Fragment.java
Copy
package ca.netfilter; // Define package name as ca.netfilter
import android.os.Bundle; // Import Android Bundle class for data passing
import androidx.fragment.app.Fragment; // Import Fragment class for creating UI fragments
import android.text.InputType;
import android.util.Log;
import android.view.LayoutInflater; // Import layout inflater class
import android.view.View; // Import view class
import android.view.ViewGroup; // Import view container class
import android.widget.Button;


import android.widget.CompoundButton;
import android.widget.TextView;

import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import com.yoloho.libcore.util.Crypt;


/**
 * A simple {@link Fragment} subclass.
 * Use the {@link Fn1Fragment#newInstance} factory method to
 * create an instance of this fragment.
 *
 * A simple {@link Fragment} subclass.
 * Use the {@link Fn1Fragment#newInstance} factory method to
 * create an instance of this fragment.
 */

//public class Fn1Fragment extends androidx.fragment.app.Fragment {
//}
public class Fn1Fragment extends Fragment {   // Define a Fragment subclass named BlankFragment

    private static final String TAG = "Fn1Fragment"; // ✅ Add TAG

    static {
        System.loadLibrary("netfilter");
    }


    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    // TODO: Rename parameter names to match initialization parameters, e.g. ARG_ITEM_NUMBER


    // Variables are declared at the head and type.  you can use them Alone!
    public Button fn1Button,fn2Button,fn3Button,run1Button,run2Button,run3Button;
    public TextView txtUser,txtPwd;
    public TextInputEditText passwordEditText;
    public TextInputLayout passwordTextInputLayout;



    private static final String ARG_PARAM1 = "param1";   // Define key name for parameter 1
    private static final String ARG_PARAM2 = "param2";    // Define key name for parameter 2

    // TODO: Rename and change types of parameters  ---> Rename and change parameter types
    private String mParam1; // Used to save the value of param1
    private String mParam2;  // Used to save the value of param2

    public Fn1Fragment() {
        // Required empty public constructor  --> Required empty public constructor
    }

    /**
     * Use this factory method to create a new instance of  .--> Use this factory method to create a new instance of BlankFragment,
     * this fragment using the provided parameters. .--> and pass two parameters.
     *
     * @param param1 Parameter 1.--> param1 Parameter 1
     * @param param2 Parameter 2. -->param2 Parameter 2
     * @return A new instance of fragment BlankFragment.--> Return a new instance of BlankFragment
     */
    // TODO: Rename and change types and number of parameters -->Rename and modify parameter types and count
    public static Fn1Fragment newInstance(String param1, String param2) {
        Fn1Fragment fragment = new Fn1Fragment();// Create a new BlankFragment instance
        Bundle args = new Bundle(); // Create a new Bundle for passing parameters
        args.putString(ARG_PARAM1, param1);  // Put param1 into Bundle
        args.putString(ARG_PARAM2, param2); // Put param2 into Bundle
        fragment.setArguments(args);  // Set parameters to fragment
        return fragment; // Return the created fragment instance
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);  // Call parent class's onCreate method
        if (getArguments() != null) {  // If there are passed parameters
            mParam1 = getArguments().getString(ARG_PARAM1); // Get param1 and assign to mParam1
            mParam2 = getArguments().getString(ARG_PARAM2); // Get param2 and assign to mParam2
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment -->  Load layout file fragment_fn1.xml for this fragment
//        return inflater.inflate(R.layout.fragment_fn1, container, false);
        View rootView = inflater.inflate(R.layout.fragment_fn1, container, false);
        initView(rootView);  // Pass rootView
        initListener(); // ✅ Add click event binding
        return rootView;
    }


    public void initView(View rootView){
        // find the page useful tag
        // Set button binding events.
        txtUser = rootView.findViewById(R.id.editTextUsername);
        txtPwd = rootView.findViewById(R.id.passwordEditTextFn1);
        fn1Button = rootView.findViewById(R.id.buttonFn1);
        run1Button = rootView.findViewById(R.id.buttonRun1);
        fn2Button = rootView.findViewById(R.id.buttonFn2);
        run2Button = rootView.findViewById(R.id.buttonRun2);
        fn3Button = rootView.findViewById(R.id.buttonFn3);
        run3Button = rootView.findViewById(R.id.buttonRun3);
        passwordEditText = rootView.findViewById(R.id.passwordEditTextFn1);
        passwordTextInputLayout = rootView.findViewById(R.id.passwordTextInputLayout);

    }

    public void initListener(){
        run1Button.setOnClickListener(new View.OnClickListener() {  // First type: full form
            @Override
            public void onClick(View v){
                jniCall_static();
            }
        });
        fn2Button.setOnClickListener(v -> clang_Call_Java_v8());  // Second type: abbreviated form
        fn3Button.setOnClickListener(v -> clang_Call_Java_v9());
        run2Button.setOnClickListener(v -> jNI_Dynamic_Register());
        run3Button.setOnClickListener(v -> Call_Encrypted_Result());

    }


    public void Call_Encrypted_Result(){
        //Send network + connect queue, get task

//        String Plaintext = String.valueOf(txtUser.getText());
////        String Ciphertext = String.valueOf(txtPwd.getText());
//
//        //Call method and get corresponding result
//        String sign = Crypt.encrypt_data(0, Plaintext, 85);
//
//
//        passwordEditText.setText(sign);
//
//        // Send + write result
        String Plaintext = txtUser.getText().toString();
        String Ciphertext = txtPwd.getText().toString();

        // Call method and get corresponding result
        String sign = Crypt.encrypt_data(0, Plaintext, 85);

        // Display encryption result in passwordEditText
        passwordEditText.setText(sign);

    }

    public void jNI_Dynamic_Register(){
//        DynamicUtils utils = new DynamicUtils();
        int result = DynamicUtils.add(5, 7);
        System.out.println("jNI_Dynamic_Register ---> Result: " + result); // Output: Result: 12
//        String value = DynamicUtils.ssss(11,22);
//        Log.e("---->", value); //  rwxt

    }

    public void clang_Call_Java_v9(){
        String resultn9 = clangCallJavaNew.v9("October 2024",2024);
        System.out.println("Instance method---C calls Java---->Result: " + resultn9);




        // -----------------Call native method ------------- kanxue MissKing's ROM JNI tracing function test-----------
        // Create JniTraceMikrom instance and call lookForDemo method
        JniTraceMikrom jniTrace = new JniTraceMikrom();
        String result = jniTrace.lookForDemo();

        // Print return value of lookForDemo method
        Log.i(TAG, "Jni-Trace-Mikrom--case---->Result: " + result);

        // -----------------Call native method ------------- kanxue MissKing's ROM JNI tracing function test-----------------




        clangCallJavaNewExampleEncrypted resultv10 = EncryptUtils.v10("aid=123488384&page=199&size=100");
        if (resultv10 != null) {
            String resultv10_string = resultv10.toString();
            Log.e("---->", resultv10_string);
        } else {
            Log.e("---->", "Error: resultv10 is null.");
        }
    }
    public void clang_Call_Java_v8(){
        // Static method  (C calls Java)
        String resultn8 = clangCallJavaStatic.v8();
//        System.out.println(clangCallJavaStatic.v8());
        System.out.println("Static method---C calls Java---->Result: " + resultn8);
    }
    public void jniCall_static(){
        // 5.5 Character processing
//        String resultn5 = EncryptUtils.v5("name=wupeiqi&age=19");
        EncryptUtils.v5("name=wupeiqi&age=19");
//        System.out.println("5.5 Character processing--> Result: " + resultn5);
        // 5.6 Byte processing
//        String resultn6 = EncryptUtils.v6(   "name=wupeiqi&age=19".getBytes()    );
        EncryptUtils.v6(   "name=wupeiqi&age=19".getBytes()    );
//        System.out.println("5.6 Byte processing--> Result: " + resultn6);

        EncryptUtils.v7(   "name=wupeiqi&age=19".getBytes()    );
    }

    public void jniCall(){

        // JNI C (native variable already declared in Java's EncryptUtils class)
        // Call core algorithm, get signature value, send to backend API.
        String signString = EncryptUtils.v0(11, "alex");
        // More awesome algorithm, let it be implemented in C language.
        int sign1 = EncryptUtils.v1(2, 3);
        Log.e("Fn1--》Test Java calls C V1 function---->", String.valueOf(sign1)); //  133

        // Java calls JNI C language --V2 function
        String sign2 = EncryptUtils.v2("root");
        Log.e("Fn1--》Test calling Native V2 function----->",sign2);


        // Java calls JNI C language --V4 function
        // JNI CPP
//        TextView tv4 = findViewById(R.id.buttonRun1);
        String signV4 = EncryptUtils.v4("called","students");
        //tv.setText(EncryptUtils.v4("called","students"));
        fn1Button.setText(signV4);

        Log.e("Fn1--》Test calling Native V4 function----->",signV4);
    }

}

Definition of user login request #

☕
/home/calleng/AndroidStudioProjects/NetFilter_PJ/app/src/main/java/ca/netfilter/ui/login/LoginFragment.java
Copy
private void doLogin() {
        String username = binding.username.getText().toString();
        String password = binding.password.getText().toString();

        TreeMap<String, String> map = new TreeMap<>();
        map.put("user", username);
        map.put("pwd", password);

        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        sb.deleteCharAt(sb.length() - 1); // Remove the final '&'

        String signString = md5(sb.toString());
        map.put("sign", signString);

        new Thread(() -> {
            try {
                Retrofit retrofit = new Retrofit.Builder()
                        .baseUrl("http://192.168.9.101:8081")
                        .build();
                HttpReq req = retrofit.create(HttpReq.class);   // Create a Retrofit interface
                // Send using form format
                // Call<ResponseBody> call = req.postLogin("xianning","password_good");
                // Send using form format

                // Send using JSON format

                JSONObject json = new JSONObject(map);
                String jsonString = json.toString();

                RequestBody form = RequestBody.create(
                        MediaType.parse("application/json;charset=utf-8"),
                        jsonString);
                Call<ResponseBody> call = req.postLoginJson(form); // Call method name, method name needs to pass parameters
                // Send using JSON format

                //  ResponseBody responseBody =  req.postLoginJson( RequestBody.create(MediaType.parse("application/json;charset=utf-8"),jsonString)).execute().body()
                ResponseBody responseBody = call.execute().body();// Execute method,
                if (responseBody == null) {
                    Log.e("Login", "Response body is null");
                    return;
                }

                String responseString = responseBody.string();//   Get return value after execution
                // The continuous operation is , req.postLoginJson( RequestBody.create(MediaType.parse("application/json;charset=utf-8"),jsonString)).execute().body().string()

                // {"code":200,"msg":"ok","token":"jfieefjeifjei-jefjeifejf-ejfiefi-100"}
                HttpResponse obj = new Gson().fromJson(responseString, HttpResponse.class);

                //Log.e("Retrofit return result",responseString);
                Log.e("Retrofit return result", obj.token);// Output Gson deserialization

                // Get server credentials, write to local xml file
                // Write to SharedPreferences
                Context context = getContext();
                if (context != null) {
                    SharedPreferences sp = context.getSharedPreferences("s_city", Context.MODE_PRIVATE);
                    SharedPreferences.Editor editor = sp.edit();
                    editor.putString("token", obj.token);
                    editor.apply();

                    // Read token value from local xml file
                    String token = sp.getString("token", "");
                    Log.e("Read token value from local xml file", token);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

user login request api #

🐍
/home/calleng/p9/Mikrom2.0/ToolKit/杂七杂八工具箱/Android_Http_API.py
Copy
from flask import Flask, jsonify, request

app = Flask(__name__)


@app.route('/auth',methods=["GET","POST"])
def auth():

    """
    # 1,Get data (Form format)
    username = request.form.get("user")
    password = request.form.get("pwd")
    sign = request.form.get('sign')
    print(username,password,sign)
    """
    # 1,Get data
    print(request.data)  # Get raw format
    # print(request.json)
    print(request.form)
    print(request.headers)


    # 2,Verify signature validity

    # 3,Business processing
    return jsonify({"code":200,"msg":"ok","token":"jfieefjeifjei-jefjeifejf-ejfiefi-100"})

@app.route('/users',methods=["GET","POST"])
def users():
    # print(request.data)  # Get raw format
    print(request.json)
    print(request.form)
    print(request.headers)

    return jsonify({"code":200,"msg":"ok","token":"jfieefjeifjei-jefjeifejf-ejfiefi-100"})



if __name__ == '__main__':
    # app.run(host='127.0.0.1', port=8080)
    # app.run(host='10.10.10.236', port=8080)
    app.run(host='0.0.0.0', port=8081)

Network Request Flow #

Step 1: Request Method #

☕
Java
Copy
private void doLogin() {
    String username = binding.username.getText().toString();
    String password = binding.password.getText().toString();

    // 1. Construct request data
    TreeMap<String, String> map = new TreeMap<>();
    map.put("user", username);
    map.put("pwd", password);

    // 2. Generate MD5 signature
    String signString = md5("pwd=" + password + "&user=" + username);
    map.put("sign", signString);

    // 3. Async network request
    new Thread(() -> {
        try {
            // Use Retrofit to send request
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://192.168.9.101:8081")
                    .build();

            HttpReq req = retrofit.create(HttpReq.class);

            // Convert to JSON format
            JSONObject json = new JSONObject(map);
            String jsonString = json.toString();

            // Create request body
            RequestBody form = RequestBody.create(
                    MediaType.parse("application/json;charset=utf-8"),
                    jsonString);

            // Send request
            Call<ResponseBody> call = req.postLoginJson(form);
            ResponseBody responseBody = call.execute().body();

            if (responseBody != null) {
                String responseString = responseBody.string();
                // Handle response data...
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }).start();
}

Step2:Form Format Comparison –> Form Format (application/x-www-form-urlencoded) #

☕
Java
Copy
// Construct Form data
FormBody.Builder formBuilder = new FormBody.Builder()
    .add("user", "calleng")
    .add("pwd", "2022")
    .add("sign", "5f4dcc3b5aa765d61d8327deb882cf99");

RequestBody formBody = formBuilder.build();

HTTP Request Example:

POST /auth HTTP/1.1
Host: 192.168.9.101:8081
Content-Type: application/x-www-form-urlencoded
Content-Length: 58

pwd=2022&user=calleng&sign=5f4dcc3b5aa765d61d8327deb882cf99

JSON Format (application/json) – Currently Used

☕
Java
Copy
// Construct JSON data
TreeMap<String, String> map = new TreeMap<>();
map.put("user", "calleng");
map.put("pwd", "2022");
map.put("sign", "5f4dcc3b5aa765d61d8327deb882cf99");

JSONObject json = new JSONObject(map);
String jsonString = json.toString();

RequestBody jsonBody = RequestBody.create(
    MediaType.parse("application/json;charset=utf-8"),
    jsonString
);

HTTP Request Example:

POST /auth HTTP/1.1
Host: 192.168.9.101:8081
Content-Type: application/json;charset=utf-8
Content-Length: 78

{
  "pwd": "2022",
  "user": "calleng",
  "sign": "5f4dcc3b5aa765d61d8327deb882cf99"
}

Step 3: Retrofit Configuration Code . Retrofit Interface Definition #

☕
HttpReq.java
Copy
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
import retrofit2.http.GET;

public interface HttpReq {

    // JSON format POST request
    @POST("/auth")
    Call<ResponseBody> postLoginJson(@Body RequestBody body);

    // Form format POST request (optional)
    @POST("/auth")
    @FormUrlEncoded
    Call<ResponseBody> postLoginForm(
        @Field("user") String user,
        @Field("pwd") String pwd,
        @Field("sign") String sign
    );

    // GET request to get user info
    @GET("/users")
    Call<ResponseBody> getUserInfo();
}
☕
Retrofit Client Configuration
Copy
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClient {

    private static Retrofit retrofit = null;

    // Basic configuration
    public static Retrofit getBasicClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("http://192.168.9.101:8081")
                    .build();
        }
        return retrofit;
    }

    // Configuration with Gson converter
    public static Retrofit getGsonClient() {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("http://192.168.9.101:8081")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }

    // Configuration with OkHttp client
    public static Retrofit getFullClient(OkHttpClient client) {
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl("http://192.168.9.101:8081")
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

Step 4: Request Interceptor #

☕
Logging Interceptor Implementation
Copy
import okhttp3.logging.HttpLoggingInterceptor;

public class LoggingInterceptor {
    public static HttpLoggingInterceptor getInterceptor() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY); // Log complete request and response info
        return logging;
    }
}
☕
Header Interceptor
Copy
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

public class HeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        Request requestWithHeaders = originalRequest.newBuilder()
                .addHeader("User-Agent", "Android-NetFilter/1.0")
                .addHeader("Accept", "application/json")
                .addHeader("Content-Type", "application/json;charset=utf-8")
                .addHeader("X-App-Version", "1.0.0")
                .build();

        return chain.proceed(requestWithHeaders);
    }
}
☕
Authentication Interceptor
Copy
import android.content.Context;
import android.content.SharedPreferences;

public class AuthInterceptor implements Interceptor {
    private Context context;

    public AuthInterceptor(Context context) {
        this.context = context;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();

        // Read Token from SharedPreferences
        SharedPreferences sp = context.getSharedPreferences("s_city", Context.MODE_PRIVATE);
        String token = sp.getString("token", "");

        if (!token.isEmpty()) {
            Request requestWithAuth = originalRequest.newBuilder()
                    .addHeader("Authorization", "Bearer " + token)
                    .build();
            return chain.proceed(requestWithAuth);
        }

        return chain.proceed(originalRequest);
    }
}
☕
Complete OkHttp Client Configuration
Copy
import okhttp3.OkHttpClient;
import java.util.concurrent.TimeUnit;

public class OkHttpClientFactory {

    public static OkHttpClient createClient(Context context) {
        return new OkHttpClient.Builder()
                // Add interceptors
                .addInterceptor(new HeaderInterceptor())
                .addInterceptor(new AuthInterceptor(context))
                .addInterceptor(LoggingInterceptor.getInterceptor())

                // Set timeout
                .connectTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(30, TimeUnit.SECONDS)

                // Retry mechanism
                .retryOnConnectionFailure(true)

                .build();
    }
}

Step 5: Gson Deserialization Parsing #

📄
Data Model Class Definition
Copy
// Response data model
public class HttpResponse {
    public int code;
    public String msg;
    public String token;
    public User data; // Optional user data

    @Override
    public String toString() {
        return "HttpResponse{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", token='" + token + '\'' +
                '}';
    }
}

// User data model (optional)
public class User {
    public String id;
    public String username;
    public String email;
    public long createTime;
}
☕
Gson Parsing Code
Copy
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class GsonParser {

    // 1. Basic object parsing
    public static HttpResponse parseResponse(String jsonString) {
        Gson gson = new Gson();
        HttpResponse response = gson.fromJson(jsonString, HttpResponse.class);
        return response;
    }

    // 2. Parsing with generics
    public static List<User> parseUserList(String jsonString) {
        Gson gson = new Gson();
        Type type = new TypeToken<List<User>>(){}.getType();
        return gson.fromJson(jsonString, type);
    }

    // 3. Manual parsing (more flexible)
    public static void manualParse(String jsonString) {
        try {
            JSONObject jsonObject = new JSONObject(jsonString);

            int code = jsonObject.getInt("code");
            String msg = jsonObject.getString("msg");
            String token = jsonObject.optString("token", ""); // optString avoids exceptions

            if (code == 200) {
                Log.i("GsonParse", "Login successful: " + token);
            } else {
                Log.e("GsonParse", "Login failed: " + msg);
            }

        } catch (Exception e) {
            Log.e("GsonParse", "Parsing failed: " + e.getMessage());
        }
    }
}
☕
Using Gson in Network Requests
Copy
private void doLoginWithGson() {
    // ... previous network request code

    // After receiving response
    String responseString = responseBody.string();

    // Method 1: Direct parsing
    HttpResponse response = GsonParser.parseResponse(responseString);
    Log.e("GsonParsingResult", "Token: " + response.token);

    // Method 2: Manual parsing
    GsonParser.manualParse(responseString);

    // Method 3: Use Gson instance
    Gson gson = new Gson();
    HttpResponse obj = gson.fromJson(responseString, HttpResponse.class);
    Log.e("DirectGsonParsing", obj.token);
}

Step 6: XML File Save Code #

☕
SharedPreferences Storage (actually XML format)
Copy
import android.content.Context;
import android.content.SharedPreferences;

public class PreferenceManager {
    private Context context;
    private SharedPreferences sharedPreferences;

    public PreferenceManager(Context context) {
        this.context = context;
        this.sharedPreferences = context.getSharedPreferences("s_city", Context.MODE_PRIVATE);
    }

    // Save Token
    public void saveToken(String token) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("token", token);
        editor.putString("login_time", String.valueOf(System.currentTimeMillis()));
        editor.apply(); // Async save

        Log.i("SharedPreferences", "Token saved: " + token);
    }

    // Read Token
    public String getToken() {
        return sharedPreferences.getString("token", "");
    }

    // Save user info
    public void saveUserInfo(String username, String userId) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("username", username);
        editor.putString("user_id", userId);
        editor.putBoolean("is_logged_in", true);
        editor.apply();
    }

    // Clear all data
    public void clearAllData() {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.clear();
        editor.apply();
        Log.i("SharedPreferences", "All data cleared");
    }
}
☕
Real XML File Operations
Copy
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

public class XmlManager {
    private Context context;
    private String xmlFileName = "login_data.xml";

    public XmlManager(Context context) {
        this.context = context;
    }

    // Save data to XML file
    public void saveToXml(String token, String username, String userId) {
        try {
            // Get file path
            File xmlFile = new File(context.getFilesDir(), xmlFileName);

            // Create Document
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.newDocument();

            // Create root element
            Element rootElement = doc.createElement("LoginData");
            doc.appendChild(rootElement);

            // Create user info element
            Element userElement = doc.createElement("User");
            rootElement.appendChild(userElement);

            // Add child elements
            createElement(doc, userElement, "Token", token);
            createElement(doc, userElement, "Username", username);
            createElement(doc, userElement, "UserId", userId);
            createElement(doc, userElement, "LoginTime", String.valueOf(System.currentTimeMillis()));

            // Save to file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(xmlFile);

            transformer.transform(source, result);

            Log.i("XMLFile", "Data saved successfully: " + xmlFile.getAbsolutePath());

        } catch (Exception e) {
            Log.e("XMLFile", "Save failed: " + e.getMessage());
        }
    }

    // Helper method to create elements
    private void createElement(Document doc, Element parent, String tagName, String textContent) {
        Element element = doc.createElement(tagName);
        element.setTextContent(textContent);
        parent.appendChild(element);
    }

    // Read XML file
    public void readFromXml() {
        try {
            File xmlFile = new File(context.getFilesDir(), xmlFileName);

            if (!xmlFile.exists()) {
                Log.w("XMLFile", "File does not exist");
                return;
            }

            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(xmlFile);

            Element root = doc.getDocumentElement();
            Element userElement = (Element) root.getElementsByTagName("User").item(0);

            String token = getElementText(userElement, "Token");
            String username = getElementText(userElement, "Username");
            String loginTime = getElementText(userElement, "LoginTime");

            Log.i("XMLRead", "Token: " + token);
            Log.i("XMLRead", "Username: " + username);
            Log.i("XMLRead", "LoginTime: " + loginTime);

        } catch (Exception e) {
            Log.e("XMLFile", "Read failed: " + e.getMessage());
        }
    }

    // Helper method to get element text
    private String getElementText(Element parent, String tagName) {
        Element element = (Element) parent.getElementsByTagName(tagName).item(0);
        return element != null ? element.getTextContent() : "";
    }
}
☕
Using Storage in Network Requests
Copy
private void handleLoginResponse(HttpResponse response) {
    if (response.code == 200) {
        // 1. Use SharedPreferences to save
        PreferenceManager preferenceManager = new PreferenceManager(getContext());
        preferenceManager.saveToken(response.token);
        preferenceManager.saveUserInfo("calleng", "12345");

        // 2. Use XML file to save
        XmlManager xmlManager = new XmlManager(getContext());
        xmlManager.saveToXml(response.token, "calleng", "12345");

        // 3. Read and verify
        String savedToken = preferenceManager.getToken();
        Log.i("StorageVerification", "Saved Token: " + savedToken);

        xmlManager.readFromXml(); // Read XML file content

    } else {
        Log.e("LoginFailed", response.msg);
    }
}

Summary #

Data Flow: #

User Input 
→ Construct Form 
→ MD5 Signature 
→ JSON Serialization 
→ Retrofit Send 
→ Interceptor Process 
→ Server Response 
→ Gson Parse 
→ XML Save
💻
dipper:/data/data/ca.netfilter/shared_prefs # cat s_city.xml
Copy
dipper:/data/data/ca.netfilter # cd shared_prefs/                                                                             
dipper:/data/data/ca.netfilter/shared_prefs # ls
s_city.xml
dipper:/data/data/ca.netfilter/shared_prefs # cat s_city.xml                                                                  
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="token">jfieefjeifjei-jefjeifejf-ejfiefi-100</string>
</map>
dipper:/data/data/ca.netfilter/shared_prefs #

Key Components: #

  1. Retrofit2 – Network request framework
  2. OkHttp – HTTP client + interceptors
  3. Gson – JSON serialization/deserialization
  4. SharedPreferences – Lightweight XML storage
  5. DOM Parser – Standard XML file operations
What are your Feelings
Still stuck? How can we help?

How can we help?

Updated on November 2, 2025
Simple Android App Networking RequestSimple Android App Networking Request

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Table of Contents
  • Android UI and background logic
    • android UI
    • User Login Interface
    • Function Interface
    • Function Button Background Logic
    • Definition of user login request
    • user login request api
  • Network Request Flow
    • Step 1: Request Method
    • Step2:Form Format Comparison --> Form Format (application/x-www-form-urlencoded)
    • Step 3: Retrofit Configuration Code . Retrofit Interface Definition
    • Step 4: Request Interceptor
    • Step 5: Gson Deserialization Parsing
    • Step 6: XML File Save Code
  • Summary
    • Data Flow:
    • Key Components:
Products
  • Native Hook
  • Kernel Hook
  • Memory CRC
  • IDA Pro Plugins
  • Frida Stalker
  • eBPF Development
  • gojue eCapture
  • stackplz Plus
  • eBPF Development
Support
  • Contact Us
  • Documentation
Company
  • Privacy Policy
  • Terms and Conditions
  • Refund Policy
Our Partners
  • Hex Rays
  • Ole André Vadla Ravnås
  • skylot / jadx
  • Jeb Pro
Stay Connected
Subscribe to our newsletter
  • YouTube
  • GitHub
  • Twitter
Copyright 2025 NullFlag LLC All Rights Reserved.
Scroll to top