简体   繁体   中英

How to download file from an URL inside a JSON in Android Studio

I have this API that sends out a response in JSON. I wanted to download the file from the URL that is included from the JSON response. How can I download this file in Android Studio using Java as the main language?

I have been testing the method for DownloadFileFromUrl using a static link and I have found out that I can download the files I needed using this method. But when I'm trying to fetch and parse the URL given by the JSON response, I got NetworkOnMainThreadException Error. Is there any way to fix this error or maybe a new and more efficient way to fetch and parse the URL?

The URL of the request is http://bryanyehuda.my.id/upload/file.php?apicall=getfiles
The HTTPGetCall is the one that throws the NetworkOnMainThreadException Error on line:

if (conn.getResponseCode() == HttpURLConnection.HTTP_OK)

This is the DownloadFile.java

public class DownloadFile extends AppCompatActivity {

    ImageButton download;
String DOWNLOAD_URL = Endpoints.GET_FILE_URL;
private ProgressDialog pDialog;
public static final int progress_bar_type = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_download_file);


    download = (ImageButton) findViewById(R.id.downloadFile);
    String result = null;
    try {
        result = HTTPGetCall(DOWNLOAD_URL);
    } catch (IOException e) {
        e.printStackTrace();
    }
    JSONObject obj = null;
    try {
        assert result != null;
        obj = new JSONObject(result);
    } catch (JSONException e) {
        e.printStackTrace();
    }
    String finalFileLink = null;
    try {
        assert obj != null;
        finalFileLink = obj.getString("file");
    } catch (JSONException e) {
        e.printStackTrace();
    }
    String finalFileLink1 = finalFileLink;
    download.setOnClickListener(v -> new DownloadFileFromURL().execute(finalFileLink1));
}

@Override
protected Dialog onCreateDialog(int id) {
    if (id == progress_bar_type) {
        pDialog = new ProgressDialog(this);
        pDialog.setMessage("Downloading file. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setMax(100);
        pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        pDialog.setCancelable(true);
        pDialog.show();
        return pDialog;
    }
    return null;
}

protected String HTTPGetCall(String WebMethodURL) throws IOException {
    StringBuilder response = new StringBuilder();
    URL u = new URL(WebMethodURL);
    HttpURLConnection conn = (HttpURLConnection) u.openConnection();

    if (conn.getResponseCode() == HttpURLConnection.HTTP_OK)
    {
        BufferedReader input = new BufferedReader(new InputStreamReader(conn.getInputStream()),8192);
        String line;
        while ((line = input.readLine()) != null)
        {
            response.append(line);
        }
        input.close();
    }
    return response.toString();
}

@SuppressLint("StaticFieldLeak")
class DownloadFileFromURL extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        showDialog(progress_bar_type);
    }

    @Override
    protected String doInBackground(String... f_url) {
        int count;
        try {
            URL url = new URL(f_url[0]);
            URLConnection connection = url.openConnection();
            connection.connect();

            int lenghtOfFile = connection.getContentLength();
            InputStream input = new BufferedInputStream(url.openStream(), 8192);
            OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/2011.pdf");

            byte[] data = new byte[1024];
            long total = 0;
            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress("" + (int) ((total * 100) / lenghtOfFile));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();

        } catch (Exception e) {
            Log.e("Error: ", e.getMessage());
        }
        return null;
    }

    protected void onProgressUpdate(String... progress) {
        pDialog.setProgress(Integer.parseInt(progress[0]));
    }

    @Override
    protected void onPostExecute(String file_url) {
        dismissDialog(progress_bar_type);
    }
}
}

This is the file.php

<?php 
 
 //Constants for database connection
 define('DB_HOST','xxxxx');
 define('DB_USER','xxxxx');
 define('DB_PASS','xxxxx');
 define('DB_NAME','xxxxx');
 define('UPLOAD_PATH', 'xxxxx/');
 
 //connecting to database 
 $conn = new mysqli(DB_HOST,DB_USER,DB_PASS,DB_NAME) or die('Unable to connect');
 $response = array();
 if(isset($_GET['apicall'])){
 switch($_GET['apicall']){
 
 //if it is an upload call we will upload the file
 case 'uploadfile':
 
 if(isset($_FILES['file']['name']) && isset($_POST['date'])){
 try{
 move_uploaded_file($_FILES['file']['tmp_name'], UPLOAD_PATH . $_FILES['file']['name']);
 $stmt = $conn->prepare("INSERT INTO files (file, date) VALUES (?,?)");
 $stmt->bind_param("ss", $_FILES['file']['name'],$_POST['date']);
 if($stmt->execute()){
 $response['error'] = false;
 $response['message'] = 'File Sukses Terupload';
 }else{
 throw new Exception("Tidak Bisa Mengupload File");
 }
 }catch(Exception $e){
 $response['error'] = true;
 $response['message'] = 'Tidak Bisa Mengupload File';
 }
 
 }else{
 $response['error'] = true;
 $response['message'] = "Ada Parameter Yang Kurang";
 }
 break;
 
 //in this call we will fetch all the files 
 case 'getfiles':
 
 $server_ip = gethostbyname(gethostname());
 $stmt = $conn->prepare("SELECT id, file, date FROM files ORDER BY id DESC LIMIT 0, 1");
 $stmt->execute();
 $stmt->bind_result($id, $file, $date);
 $files = array();
 
 while($stmt->fetch()){
 $temp = array();
 $temp['id'] = $id; 
 $temp['file'] = 'http://' . $server_ip . '/upload/'. UPLOAD_PATH . $file; 
 $temp['date'] = $date; 
 
 array_push($files, $temp);
 }
 
 //pushing the array in response 
 $response['error'] = false;
 $response['files'] = $files; 
 break; 
 
 default: 
 $response['error'] = true;
 $response['message'] = 'Invalid api call';
 }
 
 }else{
 header("HTTP/1.0 404 Not Found");
 echo "<h1>Connected</h1>";
 echo "The Database Connection is Successful.";
 exit();
 }
 
 //displaying the response in json 
 header('Content-Type: application/json');
 echo json_encode($response);
 

The problem is that you attempt to do it in your main thread.

This answer suggest the use of AsyncTask: How can I fix 'android.os.NetworkOnMainThreadException'?

but it's deprecated, so you will need to use java.util.concurrent instead.

Here is an example of that: https://www.baeldung.com/java-util-concurrent

Try sending your request that way and let me know about the results.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM