2525import org .andresoviedo .util .android .ContentUtils ;
2626import org .andresoviedo .util .android .FileUtils ;
2727import org .andresoviedo .util .view .TextActivity ;
28+ import org .json .JSONArray ;
29+ import org .json .JSONException ;
30+ import org .json .JSONObject ;
2831
2932import java .io .File ;
3033import java .io .IOException ;
3134import java .net .MalformedURLException ;
3235import java .net .URI ;
3336import java .net .URISyntaxException ;
3437import java .net .URL ;
38+ import java .util .ArrayList ;
39+ import java .util .Collections ;
3540import java .util .HashMap ;
41+ import java .util .Iterator ;
3642import java .util .List ;
3743import java .util .Locale ;
3844import java .util .Map ;
3945
46+ import de .javagl .jgltf .model .io .IO ;
47+
4048public class MenuActivity extends ListActivity {
4149
4250 private static final URL REPO_URL = createURL ("https://github.com/the3deers/android-3D-model-viewer/raw/master/models/index" );
51+ private static final URL REPO_KHRONOS_URL = createURL ("https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/model-index.json" );
4352 private static final int REQUEST_READ_EXTERNAL_STORAGE = 1000 ;
4453 private static final int REQUEST_INTERNET_ACCESS = 1001 ;
4554 private static final int REQUEST_READ_CONTENT_PROVIDER = 1002 ;
@@ -48,7 +57,7 @@ public class MenuActivity extends ListActivity {
4857 private static final int REQUEST_CODE_OPEN_MATERIAL = 1102 ;
4958 private static final int REQUEST_CODE_OPEN_TEXTURE = 1103 ;
5059 private static final int REQUEST_CODE_ADD_FILES = 1200 ;
51- private static final String SUPPORTED_FILE_TYPES_REGEX = "(?i).*\\ .(obj|stl|dae|index)" ;
60+ private static final String SUPPORTED_FILE_TYPES_REGEX = "(?i).*\\ .(obj|stl|dae|gltf| index)" ;
5261
5362
5463 private enum Action {
@@ -155,7 +164,7 @@ private void loadModel() {
155164 if (which == 0 ) {
156165 loadModelFromAssets ();
157166 } else if (which == 1 ) {
158- loadModelFromRepository (REPO_URL );
167+ loadModelFromRepository ();
159168 } else if (which == 2 ) {
160169 loadModelFromContentProvider ();
161170 } else {
@@ -165,6 +174,31 @@ private void loadModel() {
165174
166175 }
167176
177+ private void loadModelFromRepository () {
178+
179+ if (true ){
180+ if (AndroidUtils .checkPermission (this , Manifest .permission .INTERNET , REQUEST_INTERNET_ACCESS )) {
181+ new LoadRepoIndexTask ().execute (REPO_URL );
182+ }
183+ return ;
184+ }
185+
186+ // testing purposes only
187+ ContentUtils .showListDialog (this , "Choose Repository" ,
188+ new String []{"android-3D-model-viewer" , "Khronos glTF-Sample-Models" },
189+ (DialogInterface dialog , int which ) -> {
190+ if (which == 0 ) {
191+ if (AndroidUtils .checkPermission (this , Manifest .permission .INTERNET , REQUEST_INTERNET_ACCESS )) {
192+ new LoadRepoIndexTask ().execute (REPO_URL );
193+ }
194+ } else if (which == 1 ) {
195+ if (AndroidUtils .checkPermission (this , Manifest .permission .INTERNET , REQUEST_INTERNET_ACCESS )) {
196+ new LoadRepoKhronos ().execute (REPO_KHRONOS_URL );
197+ }
198+ }
199+ });
200+ }
201+
168202 private void loadModelFromAssets () {
169203 AssetUtils .createChooserDialog (this , "Select file" , null , "models" , SUPPORTED_FILE_TYPES_REGEX ,
170204 (String file ) -> {
@@ -181,6 +215,77 @@ private void loadModelFromRepository(URL url) {
181215 }
182216 }
183217
218+ class LoadRepoKhronos extends AsyncTask <URL , Integer , List <String >> {
219+
220+ private final ProgressDialog dialog ;
221+ private AlertDialog .Builder chooser ;
222+
223+ public LoadRepoKhronos () {
224+ this .dialog = new ProgressDialog (MenuActivity .this );
225+ }
226+
227+ @ Override
228+ protected void onPreExecute () {
229+ super .onPreExecute ();
230+ this .dialog .setMessage ("Loading..." );
231+ this .dialog .setCancelable (false );
232+ this .dialog .show ();
233+ }
234+
235+ @ Override
236+ protected List <String > doInBackground (URL ... urls ) {
237+
238+ try {
239+ // read json
240+ final String json = ContentUtils .read (urls [0 ]);
241+
242+ // parse json
243+ final JSONArray jsonArray = new JSONArray (json );
244+
245+ final List <String > files = new ArrayList <>();
246+ for (int i =0 ; i < jsonArray .length (); i ++){
247+ final JSONObject jsonObject = jsonArray .getJSONObject (i );
248+ final String name = jsonObject .getString ("name" );
249+ JSONObject variants = jsonObject .getJSONObject ("variants" );
250+ for (Iterator <String > it = variants .keys (); it .hasNext (); ) {
251+ final String variant = it .next ();
252+ final URI baseUri = IO .getParent (urls [0 ].toURI ());
253+ final String filename = variants .getString (variant );
254+ final String uri = baseUri
255+ + name + "/" + variant + "/" + filename ;
256+ files .add (uri );
257+ }
258+ }
259+
260+ // chooser
261+ chooser = ContentUtils .createChooserDialog (MenuActivity .this , "Select file" , null ,
262+ files , null , SUPPORTED_FILE_TYPES_REGEX ,
263+ (String file ) -> {
264+ if (file != null ) {
265+ launchModelRendererActivity (Uri .parse (file ));
266+ }
267+ });
268+ return files ;
269+ } catch (JSONException | URISyntaxException e ) {
270+ e .printStackTrace ();
271+ return Collections .emptyList ();
272+ }
273+ }
274+
275+ @ Override
276+ protected void onPostExecute (List <String > strings ) {
277+ if (dialog .isShowing ()) {
278+ dialog .dismiss ();
279+ }
280+ if (strings == null ) {
281+ Toast .makeText (MenuActivity .this , "Couldn't load repo index" , Toast .LENGTH_LONG ).show ();
282+ return ;
283+ }
284+
285+ chooser .create ().show ();
286+ }
287+ }
288+
184289 class LoadRepoIndexTask extends AsyncTask <URL , Integer , List <String >> {
185290
186291 private final ProgressDialog dialog ;
@@ -291,7 +396,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
291396 loadModelFromContentProvider ();
292397 break ;
293398 case REQUEST_INTERNET_ACCESS :
294- loadModelFromRepository (REPO_URL );
399+ loadModelFromRepository ();
295400 break ;
296401 case REQUEST_CODE_LOAD_MODEL :
297402 if (resultCode != RESULT_OK ) {
0 commit comments