SketchfabActivity.java
Go to the documentation of this file.
1 package com.introlab.rtabmap;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.List;
6 
7 import android.app.Activity;
8 import android.app.AlertDialog;
9 import android.app.Dialog;
10 import android.app.ProgressDialog;
11 import android.content.Context;
12 import android.content.DialogInterface;
13 import android.content.Intent;
14 import android.content.SharedPreferences;
15 import android.net.ConnectivityManager;
16 import android.net.NetworkInfo;
17 import android.os.AsyncTask;
18 import android.os.Bundle;
19 import android.preference.PreferenceManager;
20 import android.text.Editable;
21 import android.text.SpannableString;
22 import android.text.TextWatcher;
23 import android.text.method.LinkMovementMethod;
24 import android.text.util.Linkify;
25 import android.util.Log;
26 import android.view.View;
27 import android.view.View.OnClickListener;
28 import android.webkit.WebView;
29 import android.webkit.WebViewClient;
30 import android.widget.Button;
31 import android.widget.CheckBox;
32 import android.widget.EditText;
33 import android.widget.TextView;
34 import android.widget.Toast;
35 
36 public class SketchfabActivity extends Activity implements OnClickListener {
37 
38  private static final String AUTHORIZE_PATH = "https://sketchfab.com/oauth2/authorize";
39  private static final String CLIENT_ID = "RXrIJYAwlTELpySsyM8TrK9r3kOGQ5Qjj9VVDIfV";
40  private static final String REDIRECT_URI = "https://introlab.github.io/rtabmap/oauth2_redirect";
41 
42  ProgressDialog mProgressDialog;
43 
44  private Dialog mAuthDialog;
45 
46  private String mAuthToken;
47  private String mWorkingDirectory;
48 
49  EditText mFilename;
50  EditText mDescription;
51  EditText mTags;
52  CheckBox mDraft;
53  Button mButtonOk;
54 
55  private SketchfabActivity getActivity() {return this;}
56 
57  @Override
58  protected void onCreate(Bundle savedInstanceState) {
59  super.onCreate(savedInstanceState);
60  setContentView(R.layout.activity_sketchfab);
61 
62  mFilename = (EditText)findViewById(R.id.editText_filename);
63  mDescription = (EditText)findViewById(R.id.editText_description);
64  mTags = (EditText)findViewById(R.id.editText_tags);
65  mDraft = (CheckBox)findViewById(R.id.checkBox_draft);
66  mButtonOk = (Button)findViewById(R.id.button_ok);
67 
68  mProgressDialog = new ProgressDialog(this);
69  mProgressDialog.setCanceledOnTouchOutside(false);
70 
71  mAuthToken = getIntent().getExtras().getString(RTABMapActivity.RTABMAP_AUTH_TOKEN_KEY);
72  mFilename.setText(getIntent().getExtras().getString(RTABMapActivity.RTABMAP_FILENAME_KEY));
73  mWorkingDirectory = getIntent().getExtras().getString(RTABMapActivity.RTABMAP_WORKING_DIR_KEY);
74 
75  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
76  String tags = sharedPref.getString(getString(R.string.pref_key_tags), getString(R.string.pref_default_tags));
77  if(tags.isEmpty())
78  {
79  tags = getString(R.string.pref_default_tags);
80  }
81  mTags.setText(tags);
82 
83  mButtonOk.setEnabled(mFilename.getText().toString().length()>0);
84  mButtonOk.setOnClickListener(this);
85 
86  mFilename.addTextChangedListener(new TextWatcher() {
87 
88  @Override
89  public void afterTextChanged(Editable s) {}
90 
91  @Override
92  public void beforeTextChanged(CharSequence s, int start,
93  int count, int after) {
94  }
95 
96  @Override
97  public void onTextChanged(CharSequence s, int start,
98  int before, int count) {
99  mButtonOk.setEnabled(s.length() != 0);
100  }
101  });
102 
103  mFilename.setSelectAllOnFocus(true);
104  mFilename.requestFocus();
105  }
106 
107  @Override
108  public void onClick(View v) {
109  // Handle button clicks.
110  switch (v.getId()) {
111  case R.id.button_ok:
113  break;
114  default:
115  return;
116  }
117  }
118 
119  private void shareToSketchfab()
120  {
121  if(!mTags.getText().toString().isEmpty())
122  {
123  SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
124  SharedPreferences.Editor editor = sharedPref.edit();
125  editor.putString(getString(R.string.pref_key_tags), mTags.getText().toString());
126  // Commit the edits!
127  editor.commit();
128  }
129 
130  authorizeAndPublish(mFilename.getText().toString());
131  }
132 
133  private boolean isNetworkAvailable() {
134  ConnectivityManager connectivityManager
135  = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
136  NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
137  return activeNetworkInfo != null && activeNetworkInfo.isConnected();
138  }
139 
140  private void authorizeAndPublish(final String fileName)
141  {
142  if(!isNetworkAvailable())
143  {
144  // Visualize the result?
145  new AlertDialog.Builder(this)
146  .setTitle("Sharing to Sketchfab...")
147  .setMessage("Network is not available. Make sure you have internet before continuing.")
148  .setPositiveButton("Try Again", new DialogInterface.OnClickListener() {
149  public void onClick(DialogInterface dialog, int which) {
150  authorizeAndPublish(fileName);
151  }
152  })
153  .setNeutralButton("Abort", new DialogInterface.OnClickListener() {
154  public void onClick(DialogInterface dialog, int which) {
155  }
156  })
157  .show();
158  return;
159  }
160 
161  // get token the first time
162  if(mAuthToken == null)
163  {
164  Log.i(RTABMapActivity.TAG,"We don't have the token, get it!");
165 
166  WebView web;
167  mAuthDialog = new Dialog(this);
168  mAuthDialog.setContentView(R.layout.auth_dialog);
169  web = (WebView)mAuthDialog.findViewById(R.id.webv);
170  web.setWebContentsDebuggingEnabled(!RTABMapActivity.DISABLE_LOG);
171  web.getSettings().setJavaScriptEnabled(true);
172  String auth_url = AUTHORIZE_PATH+"?redirect_uri="+REDIRECT_URI+"&response_type=token&client_id="+CLIENT_ID;
173  Log.i(RTABMapActivity.TAG, "Auhorize url="+auth_url);
174  web.setWebViewClient(new WebViewClient() {
175 
176  boolean authComplete = false;
177 
178  @Override
179  public void onPageFinished(WebView view, String url) {
180  super.onPageFinished(view, url);
181 
182  //Log.i(TAG,"onPageFinished url="+url);
183  if(url.contains("error=access_denied")){
184  Log.e(RTABMapActivity.TAG, "ACCESS_DENIED_HERE");
185  authComplete = true;
186  Toast.makeText(getApplicationContext(), "Error Occured", Toast.LENGTH_SHORT).show();
187  mAuthDialog.dismiss();
188  }
189  else if (url.startsWith(REDIRECT_URI) && url.contains("access_token") && authComplete != true) {
190  //Log.i(TAG,"onPageFinished received token="+url);
191  String[] sArray = url.split("access_token=");
192  mAuthToken = (sArray[1].split("&token_type=Bearer"))[0];
193  authComplete = true;
194 
195  mAuthDialog.dismiss();
196 
197  zipAndPublish(fileName);
198  }
199  }
200  });
201  mAuthDialog.show();
202  mAuthDialog.setTitle("Authorize RTAB-Map");
203  mAuthDialog.setCancelable(true);
204  web.loadUrl(auth_url);
205  }
206  else
207  {
208  zipAndPublish(fileName);
209  }
210  }
211 
212  private void zipAndPublish(final String fileName)
213  {
214  mProgressDialog.setTitle("Upload to Sketchfab");
215  mProgressDialog.setMessage(String.format("Compressing the files..."));
216  mProgressDialog.show();
217 
218  Thread workingThread = new Thread(new Runnable() {
219  public void run() {
220  try{
221 
222  File tmpDir = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR);
223  tmpDir.mkdirs();
224  String[] fileNames = Util.loadFileList(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, false);
225  if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Deleting %d files in \"%s\"", fileNames.length, mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR));
226  for(int i=0; i<fileNames.length; ++i)
227  {
228  File f = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR + "/" + fileNames[i]);
229  if(f.delete())
230  {
231  if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Deleted \"%s\"", f.getPath()));
232  }
233  else
234  {
235  if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, String.format("Failed deleting \"%s\"", f.getPath()));
236  }
237  }
238  File exportDir = new File(mWorkingDirectory + RTABMapActivity.RTABMAP_EXPORT_DIR);
239  exportDir.mkdirs();
240 
242  {
243  String[] files = new String[0];
244  // verify if we have all files
245 
246  fileNames = Util.loadFileList(mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR, false);
247  if(fileNames.length > 0)
248  {
249  files = new String[fileNames.length];
250  for(int i=0; i<fileNames.length; ++i)
251  {
252  files[i] = mWorkingDirectory + RTABMapActivity.RTABMAP_TMP_DIR + "/" + fileNames[i];
253  }
254  }
255  else
256  {
257  if(!RTABMapActivity.DISABLE_LOG) Log.i(RTABMapActivity.TAG, "Missing files!");
258  }
259 
260  if(files.length > 0)
261  {
262  final String[] filesToZip = files;
263  final String zipOutput = mWorkingDirectory+fileName+".zip";
264  Util.zip(filesToZip, zipOutput);
265  runOnUiThread(new Runnable() {
266  public void run() {
267  mProgressDialog.dismiss();
268 
269  File f = new File(zipOutput);
270 
271  // Continue?
272  AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
273  builder.setTitle("File(s) compressed and ready to upload!");
274 
275  final int fileSizeMB = (int)f.length()/(1024 * 1024);
276  final int fileSizeKB = (int)f.length()/(1024);
277  if(fileSizeMB == 0)
278  {
279  Log.i(RTABMapActivity.TAG, String.format("Zipped files = %d KB", fileSizeKB));
280  builder.setMessage(String.format("Total size to upload = %d KB. Do you want to continue?\n\n", fileSizeKB));
281  }
282  else
283  {
284  Log.i(RTABMapActivity.TAG, String.format("Zipped files = %d MB", fileSizeMB));
285  builder.setMessage(String.format("Total size to upload = %d MB. %sDo you want to continue?\n\n"
286  + "Tip: To reduce the model size, you can also look at the Settings->Exporting options.", fileSizeMB,
287  fileSizeMB>=50?"Note that for size over 50 MB, a Sketchfab PRO account is required, otherwise the upload may fail. ":""));
288  }
289 
290 
291  builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
292  public void onClick(DialogInterface dialog, int which) {
293  mProgressDialog.setTitle("Upload to Sketchfab");
294  if(fileSizeMB == 0)
295  {
296  mProgressDialog.setMessage(String.format("Uploading model \"%s\" (%d KB) to Sketchfab...", fileName, fileSizeKB));
297  }
298  else
299  {
300  mProgressDialog.setMessage(String.format("Uploading model \"%s\" (%d MB) to Sketchfab...", fileName, fileSizeMB));
301  }
302  mProgressDialog.show();
303  new uploadToSketchfabTask().execute(zipOutput, fileName);
304  }
305  });
306  builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
307  public void onClick(DialogInterface dialog, int which) {
308  // do nothing...
309  }
310  });
311  builder.show();
312  }
313  });
314  }
315  }
316  else
317  {
318  runOnUiThread(new Runnable() {
319  public void run() {
320  mProgressDialog.dismiss();
321  Toast.makeText(getActivity(), String.format("Failed writing files!"), Toast.LENGTH_LONG).show();
322  }
323  });
324  }
325  }
326  catch(IOException ex) {
327  Log.e(RTABMapActivity.TAG, "Failed to zip", ex);
328  }
329  }
330  });
331 
332  workingThread.start();
333  }
334 
335  private class uploadToSketchfabTask extends AsyncTask<String, Void, Void>
336  {
337  String mModelUri;
338  String mModelFilePath;
339  String error = "";
340  String mFileName;
341 
342  protected void onPreExecute() {
343  //display progress dialog.
344  }
345 
346  @Override
347  protected void onPostExecute(Void result) {
348 
349  mProgressDialog.dismiss();
350  //Task you want to do on UIThread after completing Network operation
351  //onPostExecute is called after doInBackground finishes its task.
352  if(mModelFilePath!= null)
353  {
354  File f = new File(mModelFilePath);
355  f.delete(); // cleanup
356 
357  // See on sketchfab?
358  final SpannableString s = new SpannableString(
359  "Model \"" + mFileName + "\" is now processing on Sketchfab! You can click "
360  + "on the link below to see it on Sketchfab.\n\nhttps://sketchfab.com/models/"+mModelUri);
361  Linkify.addLinks(s, Linkify.WEB_URLS);
362  final AlertDialog d = new AlertDialog.Builder(getActivity())
363  .setTitle("Upload finished!")
364  .setCancelable(false)
365  .setMessage(s)
366  .setPositiveButton("Close", new DialogInterface.OnClickListener() {
367  public void onClick(DialogInterface dialog, int which) {
368  Intent resultIntent = new Intent();
369  resultIntent.putExtra(RTABMapActivity.RTABMAP_AUTH_TOKEN_KEY, mAuthToken);
370  setResult(Activity.RESULT_OK, resultIntent);
371  finish();
372  }
373  }).create();
374  d.show();
375  ((TextView)d.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
376  }
377  else
378  {
379  Toast.makeText(getApplicationContext(), String.format("Upload failed! Error=\"%s\"", error), Toast.LENGTH_SHORT).show();
380  }
381  }
382 
383  @Override
384  protected Void doInBackground(String... files) {
385  String charset = "UTF-8";
386  File uploadFile = new File(files[0]);
387  mFileName = files[1];
388  String requestURL = "https://api.sketchfab.com/v3/models";
389 
390  Log.i(RTABMapActivity.TAG, "Uploading " + files[0]);
391 
392  try {
393  MultipartUtility multipart = new MultipartUtility(requestURL, mAuthToken, charset);
394 
395  multipart.addFormField("name", mFileName);
396  multipart.addFormField("description", mDescription.getText().toString());
397  multipart.addFormField("tags", mTags.getText().toString());
398  multipart.addFormField("source", "RTAB-Map");
399  multipart.addFormField("isPublished", mDraft.isChecked()?"false":"true");
400  multipart.addFilePart("modelFile", uploadFile);
401 
402  Log.i(RTABMapActivity.TAG, "Starting multipart request");
403  List<String> response = multipart.finish();
404 
405  Log.i(RTABMapActivity.TAG, "SERVER REPLIED:");
406 
407  for (String line : response) {
408  Log.i(RTABMapActivity.TAG, line);
409  //{"uri":"https:\/\/api.sketchfab.com\/v3\/models\/XXXXXXXXX","uid":"XXXXXXXXXX"}
410  if(line.contains("\"uid\":\""))
411  {
412  String[] sArray = line.split("\"uid\":\"");
413  mModelUri = (sArray[1].split("\""))[0];
414  mModelFilePath = files[0];
415 
416  //patch model for orientation
417  /*HttpClient httpClient = new DefaultHttpClient();
418  try {
419  String patchURL = "https://api.sketchfab.com/v3/models/"+ mModelUri +"/options";
420  HttpPatch request = new HttpPatch(patchURL);
421  String json =
422  "{\n"+
423  "uid: "+ mModelUri + "\n" +
424  "shading: shadeless\n"+
425  //"orientation:\n"+
426  //"{\n"+
427  // "axis : [1, 0, 0]\n"+
428  // "angle : 0\n"+
429  //"}\n"+
430  "}";
431 
432  request.setHeader("Authorization", "Bearer " + mAuthToken);
433  StringEntity params =new StringEntity(json, "UTF-8");
434  params.setContentType("application/json");
435  request.setEntity(params);
436  HttpResponse responsePatch = httpClient.execute(request);
437  int responseStatus = responsePatch.getStatusLine().getStatusCode();
438  Log.i(RTABMapActivity.TAG, "get data responseStatus: " + responseStatus);
439 
440  }catch (Exception e) {
441  Log.e(RTABMapActivity.TAG, "Error while patching model", e);
442  error = e.getMessage();
443  }*/
444  }
445  }
446  } catch (IOException ex) {
447  Log.e(RTABMapActivity.TAG, "Error while uploading", ex);
448  error = ex.getMessage();
449  }
450  return null;
451  }
452  }
453 }
d
f
static void zip(String file, String zipFile)
Definition: Util.java:23
void authorizeAndPublish(final String fileName)
void addFilePart(String fieldName, File uploadFile)
static String[] loadFileList(String directory, final boolean databasesOnly)
Definition: Util.java:58
static native boolean writeExportedMesh(String directory, String name)
void onCreate(Bundle savedInstanceState)
void run(ClassLoader *loader)
void zipAndPublish(final String fileName)
void addFormField(String name, String value)


rtabmap
Author(s): Mathieu Labbe
autogenerated on Wed Jun 5 2019 22:41:32