package max.music_cyclon; import android.Manifest; import android.app.ActivityManager; import android.app.Dialog; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.database.DataSetObserver; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.google.samples.apps.iosched.ui.widget.SlidingTabLayout; import org.json.JSONException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.List; import java.util.UUID; import max.music_cyclon.preference.MainPreferenceActivity; import max.music_cyclon.service.LibraryService; /** * The main activity for synchronisation *

* This class manages: *

*/ public class SynchronizeActivity extends AppCompatActivity { public static final String DEFAULT_CONFIG_PATH = "configs.json"; private PagerAdapter pagerAdapter; /** * Messenger for communicating with service. */ private Messenger serviceObject = null; /** * Flag indicating whether we have called bind on the service. */ private boolean isBound; /** * The dialog which is being displayed while a sync is in progress */ private ProgressDialog syncProgress = null; /** * Target we publish for clients to send messages to IncomingHandler. */ private final Messenger mMessenger = new Messenger( new IncomingHandler(new WeakReference<>(this)) ); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_synchronize); Toolbar toolbar = (Toolbar) findViewById(R.id.my_toolbar); setSupportActionBar(toolbar); List configs = Collections.emptyList(); try { FileInputStream in = openFileInput(DEFAULT_CONFIG_PATH); configs = SynchronizeConfig.load(in); in.close(); } catch (IOException | JSONException e) { Log.e("CONFIG", "Failed loading the config", e); } pagerAdapter = new PagerAdapter(configs, getSupportFragmentManager()); if (pagerAdapter.getCount() == 0) { pagerAdapter.add(getString(R.string.default_config_name)); } final ViewPager pager = (ViewPager) findViewById(R.id.container); assert pager != null; pager.setAdapter(pagerAdapter); // Initialize tabs final SlidingTabLayout tabs = (SlidingTabLayout) findViewById(R.id.tabs); assert tabs != null; tabs.setTabLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { CharSequence name = ((TextView) v).getText(); RenameDialogFragment dialog = new RenameDialogFragment(); dialog.setPreviousName(name.toString()); dialog.setAdapter(getPagerAdapter()); dialog.show(getSupportFragmentManager(), dialog.getClass().getName()); return true; } }); tabs.setDistributeEvenly(true); tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() { @Override public int getIndicatorColor(int position) { return ContextCompat.getColor(SynchronizeActivity.this, R.color.accentColor); } }); tabs.setViewPager(pager); // Update tabs on dataset change pagerAdapter.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { tabs.setViewPager(pager); } }); View addButton = findViewById(R.id.add_button); assert addButton != null; addButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { pagerAdapter.add(UUID.randomUUID().toString().substring(0, 5)); pagerAdapter.notifyDataSetChanged(); } }); // Request permissions requestPermissions(); } private void requestPermissions() { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0 ); } } @Override protected void onStop() { super.onStop(); unbindLibraryService(); try { FileOutputStream fos = openFileOutput(DEFAULT_CONFIG_PATH, Context.MODE_PRIVATE); getPagerAdapter().save(fos); fos.close(); } catch (IOException | JSONException e) { Log.e("CONFIG", "Failed saving the config", e); } } public PagerAdapter getPagerAdapter() { return pagerAdapter; } public Dialog getSyncProgress() { return syncProgress; } public void clearSyncProgress() { syncProgress = null; } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_settings: Intent preferenceIntent = new Intent(this, MainPreferenceActivity.class); startActivity(preferenceIntent); return true; case R.id.action_version: notYetImplemented(this); break; case R.id.action_help: notYetImplemented(this); break; case R.id.action_sync: if (isServiceRunning(LibraryService.class)) { Toast.makeText(this, R.string.already_synchronizing, Toast.LENGTH_LONG).show(); return false; } startLibraryService(); bindLibraryService(); // Show sync control dialog syncProgress = new ProgressDialog(SynchronizeActivity.this); syncProgress.setMessage(getString(R.string.synchronizing)); syncProgress.setCancelable(false); // syncProgress.setButton( // DialogInterface.BUTTON_NEGATIVE, // getString(android.R.string.cancel), // new DialogInterface.OnClickListener() { // @Override // public void onClick(DialogInterface dialog, int which) { // dialog.dismiss(); // } // }); // syncProgress.show(); return true; default: return super.onOptionsItemSelected(item); } return false; } public static void notYetImplemented(Context context) { new AlertDialog.Builder(context).setMessage("Not yet implemented!").show(); } private static class IncomingHandler extends Handler { private final WeakReference activity; private IncomingHandler(WeakReference activity) { this.activity = activity; } @Override public void handleMessage(Message msg) { SynchronizeActivity activity = this.activity.get(); if (activity == null) { return; } switch (msg.what) { case LibraryService.MSG_FINISHED: activity.unbindLibraryService(); Dialog dialog = activity.getSyncProgress(); if (dialog != null) { dialog.dismiss(); activity.clearSyncProgress(); } break; default: super.handleMessage(msg); } } } /** * Class for interacting with the main interface of the service. */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { serviceObject = new Messenger(service); try { Message msg = Message.obtain(null, LibraryService.MSG_REGISTER_CLIENT); msg.replyTo = mMessenger; serviceObject.send(msg); } catch (RemoteException ignored) { // In this case the service has crashed before we could even // do anything with it; we can count on soon being // disconnected (and then reconnected if it can be restarted) // so there is no need to do anything here. } } public void onServiceDisconnected(ComponentName className) { serviceObject = null; } }; private void startLibraryService() { Intent intent = new Intent(SynchronizeActivity.this, LibraryService.class); List configs = getPagerAdapter().getConfigs(); // Update last updated for (SynchronizeConfig config : configs) { config.updateLastUpdated(); // fixme the result of LibraryService does not affect this (for example: Remote not available) } intent.putExtra( LibraryService.ARGUMENT_CONFIGS, configs.toArray(new SynchronizeConfig[configs.size()]) ); startService(intent); } private boolean isServiceRunning(Class serviceClass) { ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); List services = manager.getRunningServices(Integer.MAX_VALUE); for (ActivityManager.RunningServiceInfo service : services) { if (serviceClass.getName().equals(service.service.getClassName())) { return true; } } return false; } private void bindLibraryService() { bindService(new Intent( SynchronizeActivity.this, LibraryService.class ), mConnection, Context.BIND_AUTO_CREATE); isBound = true; } private void unbindLibraryService() { if (isBound) { if (serviceObject != null) { try { Message msg = Message.obtain(null, LibraryService.MSG_UNREGISTER_CLIENT); msg.replyTo = mMessenger; serviceObject.send(msg); } catch (RemoteException ignored) { } } // Detach our existing connection. unbindService(mConnection); isBound = false; } } }