Android retrofit 2, select video and upload to server
Android retrofit 2, select video and upload to server
I'm trying to learn android, I'm ok at it right now not great. Trying to expand my skill set.
So I'm trying to get a video to upload to the server with retrofit. My retrofit works uploading EditText etc.. I'm using the same IP address here as I do there.
In the code the camera works fine records video and renames the video, I believe the select video works fine(not totally sure on that but gallery opens I select a video and it doesn't crash so..., and the PHP allows me to post a video using post man. But when I hit the upload button crash. I'm not sure if the issue is in getting the real path, in the retrofit code, or maybe my file select doesn't work? I need a better coder to help me out here. I been looking on overstack for days. Tried multiple examples. Just not getting it to work.
I can't figure out the error. I tried to throw some toasts in there to see if I am getting an error but I don't ever get a toast. Just a crash.
Here is my code. I'm at least trying, throw me a bone.
Slim/PHP index
$app->post('/saveFile', function(Request $request, Response $response)
$response = array();
if (isset($_POST['desc']) && ($_POST['ID']) && strlen($_POST['desc']) > 0 &&
$_FILES['image']['error'] === UPLOAD_ERR_OK)
$upload = new uploads();
$file = $_FILES['image']['tmp_name'];
$desc = $_POST['desc'];
$ID = $_POST['ID'];
if ($upload->saveFile($ID, $file,
getFileExtension($_FILES['image']['name']), $desc))
$response['error'] = false;
$response['message'] = 'File Uploaded Successfullly';
else
$response['error'] = true;
$response['message'] = 'Required parameters are not available';
echo json_encode($response);
);
function getFileExtension($file)
$path_parts = pathinfo($file);
return $path_parts['extension'];
uploads.php
class uploads
private $con;
public function __construct()
require_once dirname(__FILE__) . '/DbConnect.php';
$db = new DbConnect();
$this->con = $db->connect();
public function saveFile($ID, $file, $extension, $desc)
$name = round(microtime(true) * 1000) . '.' . $extension;
$filedest = dirname(__FILE__) . UPLOAD_PATH . $name;
move_uploaded_file($file, $filedest);
$url = $server_ip = gethostbyname(gethostname());
$stmt = $this->con->prepare("INSERT INTO images (ID, description, url)
VALUES (?, ?, ?)");
$stmt->bind_param("sss", $ID, $desc, $name);
if ($stmt->execute())
return true;
else
return false;
API interface
@Multipart
@POST("saveFile")
Call<MyResponse> uploadImage(@Part MultipartBody.Part file, @Part("desc")
RequestBody desc, @Field("ID") String ID);
my activity class
public class vidcam extends Activity implements View.OnClickListener
String ID, prepend;
private final int VIDEO_REQUEST_CODE = 100;
private final int REQUEST_TAKE_GALLERY_VIDEO =22;
File video_file;
Button RecordButton, tobaitana, viduploadbutton, uploadvideo;
Uri selectedVideo;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vidcam);
RecordButton = (Button) findViewById(R.id.RecordButton);
RecordButton.setOnClickListener(this);
tobaitana = (Button) findViewById(R.id.tobaitana);
tobaitana.setOnClickListener(this);
viduploadbutton = (Button) findViewById(R.id.viduploadbutton);
viduploadbutton.setOnClickListener(this);
uploadvideo = (Button) findViewById(R.id.uploadvideo);
uploadvideo.setOnClickListener(this);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data)
if (requestCode == VIDEO_REQUEST_CODE)
Toast.makeText(getApplicationContext(), "Video Saved",
Toast.LENGTH_LONG).show();
if (resultCode == RESULT_OK)
if(requestCode == REQUEST_TAKE_GALLERY_VIDEO)
selectedVideo = data.getData();
public File getfilepath () throws IOException
File videofolder = new File("sdcard/video_app");
if (!videofolder.exists())
videofolder.mkdir();
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
prepend = "MOBILITY_" + timestamp + "_";
video_file = File.createTempFile(prepend, ".mp4", videofolder);
return video_file;
@Override
public void onClick(View view)
switch (view.getId())
case R.id.RecordButton:
Intent video_intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
File videolocation = null;
try
videolocation = getfilepath();
catch (IOException e)
e.printStackTrace();
Uri video_uri = Uri.fromFile(videolocation);
video_intent.putExtra(MediaStore.EXTRA_OUTPUT, video_uri);
video_intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(video_intent, VIDEO_REQUEST_CODE);
break;
case R.id.tobaitana:
Intent toanbait = new Intent(this, Abait.class);
startActivity(toanbait);
break;
case R.id.viduploadbutton:
Intent selectfile = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(selectfile, REQUEST_TAKE_GALLERY_VIDEO);
break;
case R.id.uploadvideo:
uploadFile(selectedVideo);
break;
public void useID()
SharedPreferences shareID = getSharedPreferences("shareID", Context.MODE_PRIVATE);
ID = shareID.getString("ID", "");
private String getRealPathFromURI(Uri contentUri)
String filePath;
Cursor cursor = getContentResolver().query(contentUri, null, null, null, null);
if(cursor == null)
filePath = contentUri.getPath();
else
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA);
filePath = cursor.getString(idx);
cursor.close();
Toast.makeText(getApplicationContext(), "realpath toast" + filePath, Toast.LENGTH_LONG).show();
return filePath;
private void uploadFile(Uri selectedVideo)
useID();
File vidfile = new File(getRealPathFromURI(selectedVideo));
if (vidfile.exists())
RequestBody requestBody = RequestBody.create(MediaType.parse(getContentResolver().getType(selectedVideo)), vidfile);
MultipartBody.Part file = MultipartBody.Part.createFormData("filename", vidfile.getName(), requestBody);
RequestBody desc = RequestBody.create(MediaType.parse("text/plain"), vidfile.getName());
Call<MyResponse> call = RetrofitClient.getInstance().getAPIService().uploadImage(file, desc, ID);
call.enqueue(new Callback<MyResponse>()
@Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response)
if (!response.body().error)
Toast.makeText(getApplicationContext(), "File Uploaded Successfully...", Toast.LENGTH_LONG).show();
else
Toast.makeText(getApplicationContext(), "Some error occurred...", Toast.LENGTH_LONG).show();
@Override
public void onFailure(Call<MyResponse> call, Throwable t)
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
);
else Toast.makeText(getApplicationContext(), "no file exists...", Toast.LENGTH_LONG).show();
I'm not sure how to do that. My computer is to old to run the emulator I put it on a S3 to test it. Basically I hit the case R.id.uploadvideo: button and it crashes.
– gtcode
Aug 29 at 1:01
Your Android Studio did not print any log about the crash?
– Now You See Me
Aug 29 at 2:24
OK, is I think I solved one problem. My S3 API is only 17. and the code I was using I think may have been to new? So I used Paul Burke method to help with that. stackoverflow.com/questions/20067508/… But I am still getting an error. java lang IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
– gtcode
Aug 29 at 2:25
I can't emulate on my laptop, it's too old. All my computer equipment is years old. I'm not rich unfortunately. So I am learning to code on older equipment.
– gtcode
Aug 29 at 2:27
1 Answer
1
Your controller method is all wrong, you have to use the Request / Response objects and than return the modified Response; My version is closer to the intended usage, but it is no way perfect, mostly because I don't have the android tools.
I hope it helps, more info here:
Request UploadedFiles HttpStatusCodes
$app->post('/saveFile', function(SlimHttpRequest $request, SlimHttpResponse $response)
$responseData = ;
$responseCode = 400;
/** @var PsrHttpMessageUploadedFileInterface $files */
$files = $request->getUploadedFiles();
/** @var string $postData */
$postData = $request->getParsedBody();
if ( !empty($postData['desc']) && ($postData['ID']) && !empty($files))
$upload = new uploads();
// use this if you are only upload one file
// otherwise loop though them all
$file = reset($files);
$desc = $postData['desc'];
$ID = $postData['ID'];
// this means the file was uploaded ok
if ( $file->getError() === UPLOAD_ERR_OK )
if ( $upload->saveFile($ID, $file, $file->getClientMediaType(), $desc) )
$responseData['error'] = false;
$responseData['message'] = 'File Uploaded Successfully';
$responseCode = 200;
else
$responseData['error'] = true;
$responseData['message'] = 'Required parameters are not available';
$responseCode = 406;
else
$responseData['error'] = true;
$responseData['message'] = 'File upload error: '. $file->getError();
$responseCode = 409;
return $response->withJson($responseData, $responseCode);
);
Uploads edit
class uploads
private $con;
public function __construct()
// you shouldn't need this if you are using Slim
// and you are doing require_once '/vendor/autoload.php' at the beginning of your
// index.php
require_once dirname(__FILE__) . '/DbConnect.php';
$db = new DbConnect();
$this->con = $db->connect();
public function saveFile($ID, PsrHttpMessageUploadedFileInterface $file, $extension, $desc)
$name = round(microtime(true) * 1000) . '.' . $extension;
$filedest = dirname(__FILE__) . UPLOAD_PATH . $name;
$file->moveTo($filedest);
$url = $server_ip = gethostbyname(gethostname());
$stmt = $this->con->prepare("INSERT INTO images (ID, description, url) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $ID, $desc, $name);
return $stmt->execute();
thank you for your reply. I think you are on the right track here. I do think there was a problem with the path before but now that i think is fixed. I am getting the ID, and the desc( which is the file name) the url post to the Database is 1535579779132.multipart/form-data and no file is actually uploading. on top of it the app crashes but it's at least posting. So there is definitely a problem between the two. PHP is not my strong point. I only learned it as much as I needed it in order to learn android. so off to google i go
– gtcode
Aug 29 at 22:03
ok I got the database data to post what I want it to post. But still not getting the file and the app crashes. But it's at least sending the ID, desc(file name) and the url(path on server) to the database.
– gtcode
Aug 29 at 23:11
ok, database fills correctly, app no longer crashes it sends a response file uploaded successfully. but I have 1 problem. No file is uploading. I have even tried on postman nothing is going up. $file = reset($files); to $file->getClientFilename() to move_uploaded_file($file, $filedest); is somehow not coded right.
– gtcode
Aug 30 at 4:06
ahh sorry, I forgot about the upload; you can pass the whole
$file
object to you uploads class; and then call $file->moveTo($filedest)
instead of move_uploaded_file
; I'll update my answer– zedling
Aug 30 at 9:22
$file
$file->moveTo($filedest)
move_uploaded_file
I seem to get an error on that Type: InvalidArgumentException Message: Upload target path is not writable File: C:xampphtdocsLearnAndroid1vendorslimslimSlimHttpUploadedFile.php Line: 231 I'm not sure that the directory is the problem. I was able to use postman to upload to it prior.
– gtcode
Aug 30 at 22:04
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Can you provide detail of the crash?
– Now You See Me
Aug 28 at 23:50