00001 package com.introlab.rtabmap;
00002
00003 import java.io.File;
00004 import java.io.IOException;
00005 import java.util.List;
00006
00007 import android.app.Activity;
00008 import android.app.AlertDialog;
00009 import android.app.Dialog;
00010 import android.app.ProgressDialog;
00011 import android.content.Context;
00012 import android.content.DialogInterface;
00013 import android.content.Intent;
00014 import android.content.SharedPreferences;
00015 import android.net.ConnectivityManager;
00016 import android.net.NetworkInfo;
00017 import android.os.AsyncTask;
00018 import android.os.Bundle;
00019 import android.preference.PreferenceManager;
00020 import android.text.Editable;
00021 import android.text.SpannableString;
00022 import android.text.TextWatcher;
00023 import android.text.method.LinkMovementMethod;
00024 import android.text.util.Linkify;
00025 import android.util.Log;
00026 import android.view.View;
00027 import android.view.View.OnClickListener;
00028 import android.webkit.WebView;
00029 import android.webkit.WebViewClient;
00030 import android.widget.Button;
00031 import android.widget.CheckBox;
00032 import android.widget.EditText;
00033 import android.widget.TextView;
00034 import android.widget.Toast;
00035
00036 public class SketchfabActivity extends Activity implements OnClickListener {
00037
00038 private static final String AUTHORIZE_PATH = "https://sketchfab.com/oauth2/authorize";
00039 private static final String CLIENT_ID = "RXrIJYAwlTELpySsyM8TrK9r3kOGQ5Qjj9VVDIfV";
00040 private static final String REDIRECT_URI = "https://introlab.github.io/rtabmap/oauth2_redirect";
00041
00042 ProgressDialog mProgressDialog;
00043
00044 private Dialog mAuthDialog;
00045
00046 private String mAuthToken;
00047 private String mWorkingDirectory;
00048
00049 EditText mFilename;
00050 EditText mDescription;
00051 EditText mTags;
00052 CheckBox mDraft;
00053 Button mButtonOk;
00054
00055 private SketchfabActivity getActivity() {return this;}
00056
00057 @Override
00058 protected void onCreate(Bundle savedInstanceState) {
00059 super.onCreate(savedInstanceState);
00060 setContentView(R.layout.activity_sketchfab);
00061
00062 mFilename = (EditText)findViewById(R.id.editText_filename);
00063 mDescription = (EditText)findViewById(R.id.editText_description);
00064 mTags = (EditText)findViewById(R.id.editText_tags);
00065 mDraft = (CheckBox)findViewById(R.id.checkBox_draft);
00066 mButtonOk = (Button)findViewById(R.id.button_ok);
00067
00068 mProgressDialog = new ProgressDialog(this);
00069 mProgressDialog.setCanceledOnTouchOutside(false);
00070
00071 mAuthToken = getIntent().getExtras().getString(RTABMapActivity.RTABMAP_AUTH_TOKEN_KEY);
00072 mFilename.setText(getIntent().getExtras().getString(RTABMapActivity.RTABMAP_FILENAME_KEY));
00073 mWorkingDirectory = getIntent().getExtras().getString(RTABMapActivity.RTABMAP_WORKING_DIR_KEY);
00074
00075 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
00076 String tags = sharedPref.getString(getString(R.string.pref_key_tags), getString(R.string.pref_default_tags));
00077 if(tags.isEmpty())
00078 {
00079 tags = getString(R.string.pref_default_tags);
00080 }
00081 mTags.setText(tags);
00082
00083 mButtonOk.setEnabled(mFilename.getText().toString().length()>0);
00084 mButtonOk.setOnClickListener(this);
00085
00086 mFilename.addTextChangedListener(new TextWatcher() {
00087
00088 @Override
00089 public void afterTextChanged(Editable s) {}
00090
00091 @Override
00092 public void beforeTextChanged(CharSequence s, int start,
00093 int count, int after) {
00094 }
00095
00096 @Override
00097 public void onTextChanged(CharSequence s, int start,
00098 int before, int count) {
00099 mButtonOk.setEnabled(s.length() != 0);
00100 }
00101 });
00102
00103 mFilename.setSelectAllOnFocus(true);
00104 mFilename.requestFocus();
00105 }
00106
00107 @Override
00108 public void onClick(View v) {
00109
00110 switch (v.getId()) {
00111 case R.id.button_ok:
00112 shareToSketchfab();
00113 break;
00114 default:
00115 return;
00116 }
00117 }
00118
00119 private void shareToSketchfab()
00120 {
00121 if(!mTags.getText().toString().isEmpty())
00122 {
00123 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
00124 SharedPreferences.Editor editor = sharedPref.edit();
00125 editor.putString(getString(R.string.pref_key_tags), mTags.getText().toString());
00126
00127 editor.commit();
00128 }
00129
00130 authorizeAndPublish(mFilename.getText().toString());
00131 }
00132
00133 private boolean isNetworkAvailable() {
00134 ConnectivityManager connectivityManager
00135 = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
00136 NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
00137 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
00138 }
00139
00140 private void authorizeAndPublish(final String fileName)
00141 {
00142 if(!isNetworkAvailable())
00143 {
00144
00145 new AlertDialog.Builder(this)
00146 .setTitle("Sharing to Sketchfab...")
00147 .setMessage("Network is not available. Make sure you have internet before continuing.")
00148 .setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
00149 public void onClick(DialogInterface dialog, int which) {
00150 authorizeAndPublish(fileName);
00151 }
00152 })
00153 .setNeutralButton("Abort", new DialogInterface.OnClickListener() {
00154 public void onClick(DialogInterface dialog, int which) {
00155 }
00156 })
00157 .show();
00158 return;
00159 }
00160
00161
00162 if(mAuthToken == null)
00163 {
00164 Log.i(RTABMapActivity.TAG,"We don't have the token, get it!");
00165
00166 WebView web;
00167 mAuthDialog = new Dialog(this);
00168 mAuthDialog.setContentView(R.layout.auth_dialog);
00169 web = (WebView)mAuthDialog.findViewById(R.id.webv);
00170 web.setWebContentsDebuggingEnabled(!RTABMapActivity.DISABLE_LOG);
00171 web.getSettings().setJavaScriptEnabled(true);
00172 String auth_url = AUTHORIZE_PATH+"?redirect_uri="+REDIRECT_URI+"&response_type=token&client_id="+CLIENT_ID;
00173 Log.i(RTABMapActivity.TAG, "Auhorize url="+auth_url);
00174 web.setWebViewClient(new WebViewClient() {
00175
00176 boolean authComplete = false;
00177
00178 @Override
00179 public void onPageFinished(WebView view, String url) {
00180 super.onPageFinished(view, url);
00181
00182
00183 if(url.contains("error=access_denied")){
00184 Log.e(RTABMapActivity.TAG, "ACCESS_DENIED_HERE");
00185 authComplete = true;
00186 Toast.makeText(getApplicationContext(), "Error Occured", Toast.LENGTH_SHORT).show();
00187 mAuthDialog.dismiss();
00188 }
00189 else if (url.startsWith(REDIRECT_URI) && url.contains("access_token") && authComplete != true) {
00190
00191 String[] sArray = url.split("access_token=");
00192 mAuthToken = (sArray[1].split("&token_type=Bearer"))[0];
00193 authComplete = true;
00194
00195 mAuthDialog.dismiss();
00196
00197 zipAndPublish(fileName);
00198 }
00199 }
00200 });
00201 mAuthDialog.show();
00202 mAuthDialog.setTitle("Authorize RTAB-Map");
00203 mAuthDialog.setCancelable(true);
00204 web.loadUrl(auth_url);
00205 }
00206 else
00207 {
00208 zipAndPublish(fileName);
00209 }
00210 }
00211
00212 private void zipAndPublish(final String fileName)
00213 {
00214 mProgressDialog.setTitle("Upload to Sketchfab");
00215 mProgressDialog.setMessage(String.format("Compressing the files..."));
00216 mProgressDialog.show();
00217
00218 Thread workingThread = new Thread(new Runnable() {
00219 public void run() {
00220 try{
00221
00222 File tmpDir = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR);
00223 tmpDir.mkdirs();
00224 String[] fileNames = Util.loadFileList(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, false);
00225 if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Deleting %d files in \"%s\"", fileNames.length, mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR));
00226 for(int i=0; i<fileNames.length; ++i)
00227 {
00228 File f = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR + "/" + fileNames[i]);
00229 if(f.delete())
00230 {
00231 if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Deleted \"%s\"", f.getPath()));
00232 }
00233 else
00234 {
00235 if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Failed deleting \"%s\"", f.getPath()));
00236 }
00237 }
00238 File exportDir = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_EXPORT_DIR);
00239 exportDir.mkdirs();
00240
00241 if(RTABMapLib.writeExportedMesh(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, RTABMapActivity.RTABMAP_TMP_FILENAME))
00242 {
00243 String[] files = new String[0];
00244
00245
00246 fileNames = Util.loadFileList(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, false);
00247 if(fileNames.length > 0)
00248 {
00249 files = new String[fileNames.length];
00250 for(int i=0; i<fileNames.length; ++i)
00251 {
00252 files[i] = mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR + "/" + fileNames[i];
00253 }
00254 }
00255 else
00256 {
00257 if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, "Missing files!");
00258 }
00259
00260 if(files.length > 0)
00261 {
00262 final String[] filesToZip = files;
00263 final String zipOutput = mWorkingDirectory+fileName+".zip";
00264 Util.zip(filesToZip, zipOutput);
00265 runOnUiThread(new Runnable() {
00266 public void run() {
00267 mProgressDialog.dismiss();
00268
00269 File f = new File(zipOutput);
00270
00271
00272 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
00273 builder.setTitle("File(s) compressed and ready to upload!");
00274
00275 final int fileSizeMB = (int)f.length()/(1024 * 1024);
00276 final int fileSizeKB = (int)f.length()/(1024);
00277 if(fileSizeMB == 0)
00278 {
00279 Log.i(RTABMapActivity.TAG, String.format("Zipped files = %d KB", fileSizeKB));
00280 builder.setMessage(String.format("Total size to upload = %d KB. Do you want to continue?\n\n", fileSizeKB));
00281 }
00282 else
00283 {
00284 Log.i(RTABMapActivity.TAG, String.format("Zipped files = %d MB", fileSizeMB));
00285 builder.setMessage(String.format("Total size to upload = %d MB. %sDo you want to continue?\n\n"
00286 + "Tip: To reduce the model size, you can also look at the Settings->Exporting options.", fileSizeMB,
00287 fileSizeMB>=50?"Note that for size over 50 MB, a Sketchfab PRO account is required, otherwise the upload may fail. ":""));
00288 }
00289
00290
00291 builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
00292 public void onClick(DialogInterface dialog, int which) {
00293 mProgressDialog.setTitle("Upload to Sketchfab");
00294 if(fileSizeMB == 0)
00295 {
00296 mProgressDialog.setMessage(String.format("Uploading model \"%s\" (%d KB) to Sketchfab...", fileName, fileSizeKB));
00297 }
00298 else
00299 {
00300 mProgressDialog.setMessage(String.format("Uploading model \"%s\" (%d MB) to Sketchfab...", fileName, fileSizeMB));
00301 }
00302 mProgressDialog.show();
00303 new uploadToSketchfabTask().execute(zipOutput, fileName);
00304 }
00305 });
00306 builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
00307 public void onClick(DialogInterface dialog, int which) {
00308
00309 }
00310 });
00311 builder.show();
00312 }
00313 });
00314 }
00315 }
00316 else
00317 {
00318 runOnUiThread(new Runnable() {
00319 public void run() {
00320 mProgressDialog.dismiss();
00321 Toast.makeText(getActivity(), String.format("Failed writing files!"), Toast.LENGTH_LONG).show();
00322 }
00323 });
00324 }
00325 }
00326 catch(IOException ex) {
00327 Log.e(RTABMapActivity.TAG, "Failed to zip", ex);
00328 }
00329 }
00330 });
00331
00332 workingThread.start();
00333 }
00334
00335 private class uploadToSketchfabTask extends AsyncTask<String, Void, Void>
00336 {
00337 String mModelUri;
00338 String mModelFilePath;
00339 String error = "";
00340 String mFileName;
00341
00342 protected void onPreExecute() {
00343
00344 }
00345
00346 @Override
00347 protected void onPostExecute(Void result) {
00348
00349 mProgressDialog.dismiss();
00350
00351
00352 if(mModelFilePath!= null)
00353 {
00354 File f = new File(mModelFilePath);
00355 f.delete();
00356
00357
00358 final SpannableString s = new SpannableString(
00359 "Model \"" + mFileName + "\" is now processing on Sketchfab! You can click "
00360 + "on the link below to see it on Sketchfab.\n\nhttps://sketchfab.com/models/"+mModelUri);
00361 Linkify.addLinks(s, Linkify.WEB_URLS);
00362 final AlertDialog d = new AlertDialog.Builder(getActivity())
00363 .setTitle("Upload finished!")
00364 .setCancelable(false)
00365 .setMessage(s)
00366 .setPositiveButton("Close", new DialogInterface.OnClickListener() {
00367 public void onClick(DialogInterface dialog, int which) {
00368 Intent resultIntent = new Intent();
00369 resultIntent.putExtra(RTABMapActivity.RTABMAP_AUTH_TOKEN_KEY, mAuthToken);
00370 setResult(Activity.RESULT_OK, resultIntent);
00371 finish();
00372 }
00373 }).create();
00374 d.show();
00375 ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
00376 }
00377 else
00378 {
00379 Toast.makeText(getApplicationContext(), String.format("Upload failed! Error=\"%s\"", error), Toast.LENGTH_SHORT).show();
00380 }
00381 }
00382
00383 @Override
00384 protected Void doInBackground(String... files) {
00385 String charset = "UTF-8";
00386 File uploadFile = new File(files[0]);
00387 mFileName = files[1];
00388 String requestURL = "https://api.sketchfab.com/v3/models";
00389
00390 Log.i(RTABMapActivity.TAG, "Uploading " + files[0]);
00391
00392 try {
00393 MultipartUtility multipart = new MultipartUtility(requestURL, mAuthToken, charset);
00394
00395 multipart.addFormField("name", mFileName);
00396 multipart.addFormField("description", mDescription.getText().toString());
00397 multipart.addFormField("tags", mTags.getText().toString());
00398 multipart.addFormField("source", "RTAB-Map");
00399 multipart.addFormField("isPublished", mDraft.isChecked()?"false":"true");
00400 multipart.addFilePart("modelFile", uploadFile);
00401
00402 Log.i(RTABMapActivity.TAG, "Starting multipart request");
00403 List<String> response = multipart.finish();
00404
00405 Log.i(RTABMapActivity.TAG, "SERVER REPLIED:");
00406
00407 for (String line : response) {
00408 Log.i(RTABMapActivity.TAG, line);
00409
00410 if(line.contains("\"uid\":\""))
00411 {
00412 String[] sArray = line.split("\"uid\":\"");
00413 mModelUri = (sArray[1].split("\""))[0];
00414 mModelFilePath = files[0];
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 }
00445 }
00446 } catch (IOException ex) {
00447 Log.e(RTABMapActivity.TAG, "Error while uploading", ex);
00448 error = ex.getMessage();
00449 }
00450 return null;
00451 }
00452 }
00453 }