Simplified Coding Android Upload Image to Python Server
Hullo everyone, "Uploading File or Epitome to Backend Server" this is something that we often need to do in many applications. Nosotros already learned this concept in many previous posts. But things keep changing in this tech world and erstwhile methods are obsolete now. That is why hither I am with this Android Upload File to Server with Progress Tutorial.
The method nosotros will learn in this post is fully updated and volition work in all devices, including Android x.
Contents
- 1 Prerequisites
- two Android Upload File to Server with Progress – Video
- 3 Designing Database
- 4 Building Epitome Upload API
- 5 Android Upload File to Server with Progress
- 5.one Creating an Android Project
- 5.2 Calculation Dependencies
- 5.3 Designing User Interface
- 5.four Choosing an Paradigm from Androids Gallery
- v.5 Setting Up Retrofit for File Upload
- 5.half-dozen Creating Some Extension Functions
- v.vii Creating Custom RequestBody
- 6 Android Upload File to Server with Progress Source Lawmaking
Prerequisites
- XAMPP Server: We volition use it for the backend, and ofcourse we volition be using PHP and MySQL hither for the backend part. Simply if you lot are comfy with some other tech for handling the backend you tin exercise it. We basically merely demand the API that will accept a file.
- Retrofit: Nosotros will be using this networking library in our Android Projection.
If you want to learn building RESTFul API, that you can utilize in your production awarding and so please subscribe to my YouTube aqueduct and comment to any video that you want a product level RESTFul API Evolution Tutorial.
You tin can also learn the basics of RESTFul API Evolution using SLIM3 PHP Framework from the below given link.
Android Networking Tutorial using PHP, MySQL & Retrofit
At present let's motion into our post. We will start by designing our database.
What we will do is nosotros will store the uploaded image to an uploads directory in the backend server and we will shop the path to that prototype in our MySQL database. And you should remember this thing, nosotros don't store files in our MySQL database, nosotros just store path to the file in the database.
Android Upload File to Server with Progress – Video
In case you lot are more than comfortable watching video tutorial, and so yous tin can watch the to a higher place playlist that explains complete step by step guide about Uploading File to Server with Progress.
But in case you are ok reading a written tutorial, keep reading, nosotros volition practise the same thing here.
Designing Database
- Nosotros volition be using a very simple table. So simply open up PhpMyAdmin (I hope your XAMPP Server is running) and create a database. In my case I accept created a table named ImageUploader.
- Now we need to create a tabular array where we will shop the uploaded files info. Run the post-obit SQL query to create a tabular array named uploads.
| CREATE Tabular array `uploads` ( `id` int(11) AUTO_INCREMENT Master Key, `path` varchar(252) Not Cypher, `description` varchar(252) Non Nada ); |
- As you can see we have 3 columns in our tabular array (id, path and description).
Building Image Upload API
- We take the database, now let's build the Image Upload API. For this I have a directory named ImageUploader inside my root folder that is htdocs for xampp.
- Inside this directory we volition create a file named DbConnect.php.
| ane 2 3 4 5 6 7 8 9 10 xi 12 xiii 14 15 16 17 xviii 19 20 21 22 | <?php //these are the server details //the username is root by default in case of xampp //password is nothing by default //and lastly nosotros have the database named android. if your database name is unlike you accept to change it $servername = "localhost"; $username = "root"; $password = ""; $database = "imageuploader"; //creating a new connection object using mysqli $conn = new mysqli($servername, $username, $countersign, $database); //if at that place is some mistake connecting to the database //with die we volition finish the farther execution past displaying a message causing the fault if ($conn-> connect_error) { dice("Connection failed: " . $conn-> connect_error); } |
- The in a higher place file will make our database connection. Now let'due south create the script that will handle the file upload.
- Create a file named Api.php and write the post-obit code.
| i 2 3 4 5 6 seven 8 9 x xi 12 13 14 xv 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 ninety 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | <?php //getting database connection require_once 'DbConnect.php'; //array to testify the response $response = assortment(); //uploads directory, we will upload all the files within this folder $target_dir = "uploads/"; //checking if we are having an api call, using the become parameters 'apicall' if(isset($_GET['apicall'])){ switch($_GET['apicall']){ //if the api call is for uploading the paradigm case 'upload': //error bulletin and error flag $message = 'Params '; $is_error = false; //validating the asking to cheque if all the required parameters are available or not if(!isset($_POST['desc'])){ $message .= "desc, "; $is_error = truthful; } if(!isset($_FILES['image']['name'])){ $bulletin .= "paradigm "; $is_error = true; } //in case nosotros have an mistake in validation, displaying the fault message if($is_error){ $response['error'] = true; $response['message'] = $message . " required."; }else{ //if validation succeeds //creating a target file with a unique proper noun, and so that for every upload we create a unique file in our server $target_file = $target_dir . uniqid() . '.'.pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION); //saving the uploaded file to the uploads directory in our target file if (move_uploaded_file($_FILES["epitome"]["tmp_name"], $target_file)) { //saving the file information to our database $stmt = $conn-> set up("INSERT INTO uploads (`path`, `description`) VALUES (?, ?)"); $stmt-> bind_param("ss", $target_file, $_POST['desc']); //if it is saved in database successfully if($stmt-> execute()){ //displaying success response $response['error'] = false; $response['message'] = 'Image Uploaded Successfully'; $response['paradigm'] = getBaseURL() . $target_file; }else{ //if not saved in database //showing response appropriately $response['fault'] = true; $response['bulletin'] = 'Could not upload image, try once again...'; } $stmt-> close(); } else { $response['error'] = truthful; $response['bulletin'] = 'Try once more afterwards...'; } } interruption; //we volition utilize this case to go all the uploaded images from the database case 'images': $stmt = $conn-> set up("SELECT `id`, `path`, `description` FROM uploads"); $stmt-> execute(); $stmt-> bind_result($id, $path, $desc); while($stmt-> fetch()){ $image = assortment(); $prototype['id'] = $id; $image['path'] = getBaseURL() . $path; $paradigm['desc'] = $desc; array_push($response, $image); } break; default: $response['fault'] = true; $response['message'] = 'Invalid Performance Chosen'; } }else{ $response['error'] = truthful; $response['message'] = 'Invalid API Call'; } part getBaseURL(){ $url = isset($_SERVER['HTTPS']) ? 'https://' : 'http://'; $url .= $_SERVER['SERVER_NAME']; $url .= $_SERVER['REQUEST_URI']; return dirname($url) . '/'; } header('Content-Type: application/json'); echo json_encode($response); |
- The above code handle two cases. The commencement 1 is to upload the file and the next is to fetch the uploaded files.
| Mail service - http://localhost/ImageUploader/Api.php?apicall=upload - prototype, desc GET - http://localhost/ImageUploader/Api.php?apicall=images |
If you lot need the source lawmaking of the PHP Scripts, and then yous can get it from the below given link.
Download PHP Scripts
So we take the APIs set up, now permit'due south create our Android Project.
Android Upload File to Server with Progress
Creating an Android Project
- I take created a new project named ImageUploader using an EmptyActivity. Once the project is loaded, we will add required dependencies and internet permission.
- First add together internet permission in your AndroidManifest.xml, you also need to add the usesCleartextTraffic="truthful".
| 1 2 iii 4 five six vii 8 ix 10 11 12 13 fourteen 15 16 17 18 19 xx 21 22 23 24 25 26 27 28 | <? xml version="1.0" encoding="utf-eight" ?> < manifest xmlns : android="http://schemas.android.com/apk/res/android" xmlns : tools="http://schemas.android.com/tools" package="net.simplifiedcoding.imageuploader" > < uses-permission android : proper noun="android.permission.INTERNET" /> < application android : allowBackup="true" android : icon="@mipmap/ic_launcher" android : characterization="@cord/app_name" android : roundIcon="@mipmap/ic_launcher_round" android : supportsRtl="true" android : theme="@manner/AppTheme" android : usesCleartextTraffic="true" tools : targetApi="thousand" > < activeness android : proper noun=".MainActivity" > < intent-filter > < action android : name="android.intent.activity.Chief" /> < category android : name="android.intent.category.LAUNCHER" /> </intent-filter > </activity > </awarding > </manifest > |
- At present we volition add the required dependencies.
Adding Dependencies
- Open app level build.gradle file and add the post-obit dependencies inside dependencies cake.
| implementation 'com.squareup.retrofit2:retrofit:ii.half-dozen.1' implementation 'com.squareup.retrofit2:converter-gson:2.6.i' implementation 'com.google.android.cloth:fabric:i.1.0' |
- After calculation these lines, sync the projection.
Designing User Interface
- At present let's design the UI. Open activity_main.xml and write the following xml code.
| 1 2 3 iv 5 6 7 eight 9 10 xi 12 thirteen xiv 15 16 17 18 19 twenty 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <? 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" xmlns : tools="http://schemas.android.com/tools" android : id="@+id/layout_root" android : layout_width="match_parent" android : layout_height="match_parent" tools : context=".MainActivity" > < LinearLayout android : id="@+id/linearLayout" android : layout_width="0dp" android : layout_height="wrap_content" android : orientation="vertical" android : padding="12dp" app : layout_constraintBottom_toBottomOf="parent" app : layout_constraintEnd_toEndOf="parent" app : layout_constraintStart_toStartOf="parent" app : layout_constraintTop_toTopOf="parent" > < ImageView android : id="@+id/image_view" android : layout_width="match_parent" android : layout_height="350dp" android : layout_margin="24dp" app : srcCompat="@drawable/ic_picture" /> < TextView android : id="@+id/textView" android : layout_width="wrap_content" android : layout_height="wrap_content" android : layout_gravity="center_horizontal" android : fontFamily="sans-serif-lite" android : text="Tap to Select Image" android : textSize="24sp" /> < ProgressBar android : id="@+id/progress_bar" style="@style/Widget.AppCompat.ProgressBar.Horizontal" android : layout_width="match_parent" android : layout_height="wrap_content" android : max="100" tools : progress="40" /> </LinearLayout > < Button android : id="@+id/button_upload" android : layout_width="wrap_content" android : layout_height="wrap_content" android : text="Upload" app : layout_constraintBottom_toBottomOf="parent" app : layout_constraintEnd_toEndOf="parent" app : layout_constraintStart_toStartOf="parent" /> </androidx . constraintlayout . widget . ConstraintLayout > |
- The above XML Code volition generate the following output.
- Every bit yous tin encounter we have a very simple User Interface for our upload performance.
- At present we need an Image to Upload it. And we will let the user choose the image from device. So our first chore here is to let the user cull the prototype to upload.
Choosing an Image from Androids Gallery
- First define a var inside your MainActivity.kt. This var volition keep the uri of the selected image file.
| private var selectedImageUri: Uri? = null |
- Now nosotros will create two different function inside our MainActivity.kt. One is to choose the paradigm that we volition employ now and other to upload the image.
- We will also attach the click listeners to our ImageView and Button to phone call the functions equally you can meet in the below code.
| image_view . setOnClickListener { openImageChooser() } button_upload . setOnClickListener { uploadImage() } |
- The above code snippet you need to put inside your onCreate() part.
- Within MainActivity.kt we will define a constant that we will use for getting the selected paradigm.
| companion object { const val REQUEST_CODE_PICK_IMAGE = 101 } |
- Now we will define the role openImageChooser() that will open the prototype picker, and we will also override the role onActivityResult() to get the selected prototype.
| one two 3 4 5 six 7 8 9 ten 11 12 13 14 15 16 17 18 19 20 21 22 | private fun openImageChooser() { Intent(Intent . ACTION_PICK).also { it . type = "image/*" val mimeTypes = arrayOf("image/jpeg", "image/png") it . putExtra(Intent . EXTRA_MIME_TYPES, mimeTypes) startActivityForResult(it, REQUEST_CODE_PICK_IMAGE) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super . onActivityResult(requestCode, resultCode, data) if (resultCode == Activity . RESULT_OK) { when (requestCode) { REQUEST_CODE_PICK_IMAGE -> { selectedImageUri = data?.information image_view . setImageURI(selectedImageUri) } } } } |
- As y'all tin encounter within the function onActivityResult() we are storing the uri of the image to the var that nosotros defined at the beginning. We are too displaying the image selected in our ImageView.
Here we accept the tricky office, we have the Uri of the epitome, simply to upload the image we need the real path of it. If you accept seen my final tutorial about Uploading Image with Retrofit, then here we have used a function that provides the real path from Uri. Merely this doesn't work anymore in Android x.
Nowadays, android recommends us to use the app directory for file storage. Every app has its own app-specific storage directory for file storage that is not accessible to other apps, and all files stored here are removed when we uninstall the application. And the expert matter is too admission this expanse you lot don't demand any permission.
So what nosotros need to do is, we need to select the file from the gallery and make a re-create of it inside the app-specific storage directory.
But earlier doing the above mentioned thing we will setup the Retrofit.
Setting Up Retrofit for File Upload
If you lot have used Retrofit earlier, yous know what we need to do. First we volition create an interface to ascertain the API Calls.
- Create a file named MyAPI.kt and write the following code in it.
| one 2 3 4 5 6 seven 8 9 10 xi 12 13 xiv 15 16 17 18 19 20 21 | interface MyAPI { @Multipart @POST("Api.php?apicall=upload") fun uploadImage( @Office image: MultipartBody . Part, @Part("desc") desc: RequestBody ): Telephone call < UploadResponse > companion object { operator fun invoke(): MyAPI { return Retrofit . Builder() .baseUrl("http://10.x.ten.118/ImageUploader/") .addConverterFactory(GsonConverterFactory . create()) .build() .create(MyAPI::class . java) } } } |
- In the to a higher place code y'all can see we didn't utilize localhost in the Base URL simply we used IP Address, now what is the IP Address in your system yous need to find it out. Cheque this post to know the details about it.
- Now yous too need to create the following data course for parsing the API Response.
| data grade UploadResponse( val error: Boolean, val message: String, val epitome: String ) |
Creating Some Extension Functions
Extension function is a bang-up feature that you go with Kotlin. Nosotros need to create two extension functions in this project, one is for getting file name from Uri and another one is for displaying snackbar (Toast looks very ho-hum at present a days).
- Create a file named Utils.kt and write the following code.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 sixteen 17 18 19 twenty 21 22 23 24 25 | fun View . snackbar(message: String) { Snackbar . make( this, message, Snackbar . LENGTH_LONG ).also { snackbar -> snackbar . setAction("Ok") { snackbar . dismiss() } }.testify() } fun ContentResolver . getFileName(fileUri: Uri): String { var name = "" val returnCursor = this . query(fileUri, cypher, null, nada, null) if (returnCursor != cipher) { val nameIndex = returnCursor . getColumnIndex(OpenableColumns . DISPLAY_NAME) returnCursor . moveToFirst() name = returnCursor . getString(nameIndex) returnCursor . close() } return proper noun } |
- Now let'south make the very important office of this project, that is a custom RequestBody.
If we desire to go the upload progress, nosotros demand to create a custom RequestBody that volition comprise the file and the other information that we demand to send with the API.
Creating Custom RequestBody
- Create a course named UploadRequestBody and write the following lawmaking in it.
| ane 2 iii iv five half-dozen vii eight nine 10 eleven 12 13 xiv fifteen xvi 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 forty 41 42 43 44 45 | form UploadRequestBody( private val file: File, private val contentType: Cord, private val callback: UploadCallback ) : RequestBody() { override fun contentType() = MediaType . parse("$contentType/*") override fun contentLength() = file . length() override fun writeTo(sink: BufferedSink) { val length = file . length() val buffer = ByteArray(DEFAULT_BUFFER_SIZE) val fileInputStream = FileInputStream(file) var uploaded = 0L fileInputStream . use { inputStream -> var read: Int val handler = Handler(Looper . getMainLooper()) while (inputStream . read(buffer).also { read = it } != -1) { handler . mail(ProgressUpdater(uploaded, length)) uploaded += read sink . write(buffer, 0, read) } } } interface UploadCallback { fun onProgressUpdate(percentage: Int) } inner class ProgressUpdater( private val uploaded: Long, private val total: Long ) : Runnable { override fun run() { callback . onProgressUpdate((100 * uploaded / total).toInt()) } } companion object { individual const val DEFAULT_BUFFER_SIZE = 2048 } } |
- Now we just need to complete the function uploadImage() within our MainActivity.kt and nosotros are washed.
| i two three iv 5 vi vii eight 9 10 11 12 thirteen 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 xxx 31 32 33 34 35 36 37 38 39 40 41 42 43 | private fun uploadImage() { if (selectedImageUri == null) { layout_root . snackbar("Select an Prototype First") return } val parcelFileDescriptor = contentResolver . openFileDescriptor(selectedImageUri!!, "r", zip) ?: return val inputStream = FileInputStream(parcelFileDescriptor . fileDescriptor) val file = File(cacheDir, contentResolver . getFileName(selectedImageUri!!)) val outputStream = FileOutputStream(file) inputStream . copyTo(outputStream) progress_bar . progress = 0 val torso = UploadRequestBody(file, "paradigm", this) MyAPI().uploadImage( MultipartBody . Part . createFormData( "image", file . proper name, trunk ), RequestBody . create(MediaType . parse("multipart/form-data"), "json") ).enqueue(object : Callback < UploadResponse > { override fun onFailure(telephone call: Telephone call < UploadResponse >, t: Throwable) { layout_root . snackbar(t . message!!) progress_bar . progress = 0 } override fun onResponse( call: Call < UploadResponse >, response: Response < UploadResponse > ) { response . body()?.let { layout_root . snackbar(it . message) progress_bar . progress = 100 } } }) } |
- After finishing the above role, you can try running your application to run into the image is getting uploaded or not.
Android Upload File to Server with Progress Source Code
In case y'all want to get my source lawmaking, y'all can become it by being Simplified Coding's Subscriber on YouTube.
So that is all for this Android Upload File to Server with Progress Tutorial friends. In example you accept any trouble or confusion, you lot can get out your comments below. And if you found this mail helpful and so please help me back past SHARING it with your friends. Thank You 🙂
Hullo, my name is Belal Khan and I am a Google Developers Practiced (GDE) for Android. The passion of teaching made me create this blog. If yous are an Android Developer, or you are learning about Android Evolution, and then I can assistance you a lot with Simplified Coding.
Source: https://www.simplifiedcoding.net/android-upload-file-to-server/
0 Response to "Simplified Coding Android Upload Image to Python Server"
Post a Comment