diff --git a/source-code/app/build.gradle b/source-code/app/build.gradle index 3ac948fd..62fd4cb2 100644 --- a/source-code/app/build.gradle +++ b/source-code/app/build.gradle @@ -68,10 +68,14 @@ dependencies { compile files('libs/prov-1.51.0.0.jar') compile files('libs/zipio-lib-1.8.jar') + compile 'com.google.android.gms:play-services-auth:9.8.0' + compile 'com.google.android.gms:play-services-drive:9.8.0' + compile 'com.squareup.picasso:picasso:2.5.2' compile 'org.jsoup:jsoup:1.9.1' - androidTestCompile 'com.android.support:support-annotations:23.4.0' + androidTestCompile 'com.android.support:support-annotations:24.0.0' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.0.0' -} \ No newline at end of file +} +apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/source-code/app/google-services.json b/source-code/app/google-services.json new file mode 100644 index 00000000..2f62af88 --- /dev/null +++ b/source-code/app/google-services.json @@ -0,0 +1,40 @@ +{ + "project_info": { + "project_number": "373868766583", + "project_id": "theta-bindery-158207" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:373868766583:android:dce0dccbf435c38d", + "android_client_info": { + "package_name": "org.buildmlearn.toolkit" + } + }, + "oauth_client": [ + { + "client_id": "373868766583-k2t8n2b4tajj0ota82ff7muu6ijlr0dp.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyD6aSOA0BXOe0mL2XQnPxfXd-7Uo5yZWs8" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 1 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/source-code/app/src/main/AndroidManifest.xml b/source-code/app/src/main/AndroidManifest.xml index 518e1da0..f321f903 100755 --- a/source-code/app/src/main/AndroidManifest.xml +++ b/source-code/app/src/main/AndroidManifest.xml @@ -92,6 +92,12 @@ + + + + + + diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/activity/HomeActivity.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/activity/HomeActivity.java index 33153f57..b2ae197d 100755 --- a/source-code/app/src/main/java/org/buildmlearn/toolkit/activity/HomeActivity.java +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/activity/HomeActivity.java @@ -1,51 +1,93 @@ package org.buildmlearn.toolkit.activity; +import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; import android.content.SharedPreferences; + import android.graphics.drawable.ColorDrawable; import android.os.Build; + + +import android.net.Uri; + import android.os.Bundle; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.NavigationView; import android.app.FragmentManager; + import android.support.v4.content.ContextCompat; + + + import android.support.v4.view.GravityCompat; import android.os.Handler; import android.support.v4.widget.DrawerLayout; import android.support.v7.app.AppCompatActivity; + import android.support.v7.widget.Toolbar; + + +import android.util.Log; +import android.view.Gravity; +import android.view.Menu; + import android.view.MenuItem; import android.view.View; +import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.auth.api.signin.GoogleSignInResult; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.common.api.Status; +import com.google.android.gms.drive.Drive; +import com.squareup.picasso.Picasso; + import org.buildmlearn.toolkit.R; import org.buildmlearn.toolkit.fragment.DraftsFragment; import org.buildmlearn.toolkit.fragment.HomeFragment; import org.buildmlearn.toolkit.fragment.LoadApkFragment; import org.buildmlearn.toolkit.fragment.LoadProjectFragment; import org.buildmlearn.toolkit.fragment.SettingsFragment; +import org.buildmlearn.toolkit.utilities.CircleTransform; import org.buildmlearn.toolkit.utilities.SmoothNavigationToggle; +import static org.buildmlearn.toolkit.R.drawable.logo_70; + /** * @brief Home screen of the application containg all the menus and settings. */ public class HomeActivity extends AppCompatActivity - implements NavigationView.OnNavigationItemSelectedListener { + implements NavigationView.OnNavigationItemSelectedListener , + GoogleApiClient.OnConnectionFailedListener,GoogleApiClient.ConnectionCallbacks{ private final String FRAGMENT_TAG_HOME = "Home"; private final String FRAGMENT_TAG_PROJECT = "Project"; private final String FRAGMENT_TAG_APK = "Apk"; private boolean backPressedOnce = false; + private static final int REQUEST_DRIVE_SIGNIN = 123; + private static final int REQUEST_GOOGLE_SIGN_IN =143; + public static GoogleApiClient mGoogleApiClient,mGoogleApiClient1; + + private Uri uri; + private SmoothNavigationToggle smoothNavigationToggle; private NavigationView navigationView; + /** * {@inheritDoc} */ @@ -66,7 +108,7 @@ protected void onCreate(Bundle savedInstanceState) { navigationView.setNavigationItemSelectedListener(this); View menuHeaderView = navigationView.getHeaderView(0); - final TextView name = (TextView) menuHeaderView.findViewById(R.id.name); + final TextView name = (TextView) menuHeaderView.findViewById(R.id.person_name); name.setText(String.format(" %s", prefs.getString(getString(R.string.key_user_name), ""))); @@ -76,7 +118,12 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); - name.setText(String.format(" %s", prefs.getString(getString(R.string.key_user_name), ""))); + if((mGoogleApiClient !=null) &&(!(mGoogleApiClient.isConnected()))){ + + name.setText("Welcome "+String.format(" %s", prefs.getString(getString(R.string.key_user_name), ""))); + + } + LoadProjectFragment f = (LoadProjectFragment) getFragmentManager().findFragmentByTag(FRAGMENT_TAG_PROJECT); if (f != null) f.closeSearch(); @@ -96,6 +143,28 @@ public void onDrawerOpened(View drawerView) { if (getSupportActionBar() != null) { getSupportActionBar().setTitle(R.string.app_name); } + + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addApi(Drive.API) + .addScope(Drive.SCOPE_FILE) + .addConnectionCallbacks(this) + .addScope(Drive.SCOPE_APPFOLDER) + .addOnConnectionFailedListener(this) + .build(); + + + GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) + .requestEmail() + .build(); + + + mGoogleApiClient1 = new GoogleApiClient.Builder(this) + .enableAutoManage(this , this ) + .addApi(Auth.GOOGLE_SIGN_IN_API, gso) + .build(); + + + } @SuppressWarnings("StatementWithEmptyBody") @@ -195,6 +264,25 @@ public void run() { } }); break; + case R.id.sign_in: + Menu menu = navigationView.getMenu(); + MenuItem aaa = menu.getItem(7); + if(mGoogleApiClient !=null){ + if("Sign Out".equals(aaa.getTitle())){ + aaa.setTitle("Sign In"); + mGoogleApiClient.clearDefaultAccountAndReconnect(); + mGoogleApiClient.disconnect(); + Auth.GoogleSignInApi.signOut(mGoogleApiClient1) + .setResultCallback(logout); + } + else { + mGoogleApiClient.connect(); + } + } + break; + default: + //do nothing + break; } DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); @@ -243,6 +331,147 @@ public void run() navigationView.setCheckedItem(R.id.nav_home); } } + + + @Override + public void onConnected(@Nullable Bundle bundle) { + + + + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient1); + startActivityForResult(signInIntent, REQUEST_GOOGLE_SIGN_IN); + } + + @Override + public void onConnectionSuspended(int i) { + if(mGoogleApiClient!=null){ + mGoogleApiClient.disconnect(); + } + + } + + @Override + public void onConnectionFailed(@NonNull ConnectionResult result) { + if (!result.hasResolution()) { + GoogleApiAvailability.getInstance().getErrorDialog(this, result.getErrorCode(), 0).show(); + return; + } + try { + result.startResolutionForResult(this, REQUEST_DRIVE_SIGNIN); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @Override + protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { + switch (requestCode) { + + case REQUEST_DRIVE_SIGNIN: + + if (resultCode == Activity.RESULT_OK) { + + mGoogleApiClient.connect(); + + } + else if (resultCode == RESULT_CANCELED){ + + Log.d("TAG","result cancelled"); + return ; + } + break; + + case REQUEST_GOOGLE_SIGN_IN: + + GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); + + if (result.isSuccess()) { + + String name = result.getSignInAccount().getDisplayName(); + String email = result.getSignInAccount().getEmail(); + uri = result.getSignInAccount().getPhotoUrl(); + TextView personname = (TextView)findViewById(R.id.person_name); + Menu menu = navigationView.getMenu(); + MenuItem aaa = menu.getItem(7); + + aaa.setTitle("Sign Out"); + Picasso.with(this).load(uri).transform(new CircleTransform()).into((ImageView)findViewById(R.id.profile_pic)); + personname.setText("Welcome " + name); + Toast.makeText(this," connected "+email,Toast.LENGTH_SHORT).show(); + + + + } + else{ + + Toast.makeText(this,"No internet",Toast.LENGTH_SHORT).show(); + } + break; + default: + //do nothing + break; + + + } + } + + + @Override + protected void onPause() { + super.onPause(); + } + + + @Override + protected void onResume() { + + super.onResume(); + if (mGoogleApiClient == null) { + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addApi(Drive.API) + .addScope(Drive.SCOPE_FILE) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .build(); + mGoogleApiClient.connect(); + } + + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if ((mGoogleApiClient != null)&& (mGoogleApiClient.isConnected())){ + + mGoogleApiClient.clearDefaultAccountAndReconnect(); + mGoogleApiClient.disconnect(); + } + if ((mGoogleApiClient1 != null)&& (mGoogleApiClient1.isConnected())){ + + Auth.GoogleSignInApi.signOut(mGoogleApiClient1) + .setResultCallback(logout); + + + } + } + + /** + * logout is result callback defined to logout user from google sign in api + */ + + private ResultCallback logout= new ResultCallback() { + @Override + public void onResult(@NonNull Status status) { + + ImageView iv = (ImageView) findViewById(R.id.profile_pic); + Picasso.with(getApplicationContext()).load(logo_70).into(iv); + TextView personname = (TextView)findViewById(R.id.person_name); + personname.setText("Welcome"); + personname.setGravity(Gravity.CENTER); + + } + }; } diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/DraftsFragment.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/DraftsFragment.java index 9ab36303..5dd2ba7c 100644 --- a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/DraftsFragment.java +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/DraftsFragment.java @@ -28,6 +28,7 @@ import org.buildmlearn.toolkit.constant.Constants; import org.buildmlearn.toolkit.model.SavedProject; import org.buildmlearn.toolkit.model.Template; +import org.buildmlearn.toolkit.service.UploadFileTask; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -42,6 +43,8 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import static org.buildmlearn.toolkit.activity.HomeActivity.mGoogleApiClient; + /** * Created by scopeinfinity on 10/3/16. */ @@ -52,6 +55,7 @@ public class DraftsFragment extends Fragment implements AbsListView.OnItemClickListener { private static final String TAG = "Draft Project Fragment"; + private static final int SAVED_DRAFT_CATEGOTY = 3; private AbsListView mListView; private boolean showTemplateSelectedMenu; @@ -320,6 +324,42 @@ public void onClick(View v) { }); break; + case R.id.action_sync_saved_project: + if(mGoogleApiClient != null){ + if(mGoogleApiClient.isConnected()) { + + final AlertDialog dialog_sync = new AlertDialog.Builder(activity) + .setTitle("Sync to Drive") + .setMessage("Do you want to save the selected drafts to your drive") + .setPositiveButton(R.string.dialog_yes, null) + .setNegativeButton(R.string.dialog_no, null) + .create(); + + dialog_sync.show(); + + dialog_sync.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog_sync.dismiss(); + syncDrafts(); + restoreSelectedView(); + } + }); + } + else{ + + Toast.makeText(getActivity(),"Drive not connected",Toast.LENGTH_SHORT).show(); + mGoogleApiClient.connect(); + } + } + else{ + + Toast.makeText(getActivity(),"Drive not connected",Toast.LENGTH_SHORT).show(); + } + + + break; + case R.id.action_select_all: for(int i=0;i selectedPositions = mAdapter.getSelectedPositions(); + if (selectedPositions.size() == 1) { + Toast.makeText(activity, "Uploading Project", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(activity, "Uploading Projects", Toast.LENGTH_SHORT).show(); + } + + for (int selectedPosition : selectedPositions) { + + SavedProject project =draftProjects.get(selectedPosition); + File file = new File(project.getFile().getPath()); + + String [] strings =new String[4]; + + strings[0]=file.getName(); + strings[1]= String.valueOf(selectedPosition); + strings[2]=String.valueOf(SAVED_DRAFT_CATEGOTY); + strings[3]=file.getPath(); + + new UploadFileTask().execute(strings); + + } + } } diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadApkFragment.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadApkFragment.java index 45c86cae..08e8c8af 100644 --- a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadApkFragment.java +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadApkFragment.java @@ -33,12 +33,15 @@ import org.buildmlearn.toolkit.ToolkitApplication; import org.buildmlearn.toolkit.adapter.SavedApiAdapter; import org.buildmlearn.toolkit.model.SavedApi; +import org.buildmlearn.toolkit.service.UploadFileTask; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import static org.buildmlearn.toolkit.activity.HomeActivity.mGoogleApiClient; + /** * Created by opticod (Anupam Das) on 29/2/16. * @@ -48,6 +51,7 @@ public class LoadApkFragment extends Fragment implements AbsListView.OnItemClickListener { private static final String TAG = "Load API Fragment"; + private static final int APK_CATEGOTY = 1; private AbsListView mListView; private boolean showTemplateSelectedMenu; @@ -340,6 +344,40 @@ public void onClick(View v) { } }); break; + + case R.id.action_sync: + + + if(mGoogleApiClient != null){ + if(mGoogleApiClient.isConnected()) { + final AlertDialog dialog_sync = new AlertDialog.Builder(activity) + .setTitle("Sync to Drive") + .setMessage("Do you want to save the selected Apks to your drive") + .setPositiveButton(R.string.dialog_yes, null) + .setNegativeButton(R.string.dialog_no, null) + .create(); + dialog_sync.show(); + dialog_sync.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog_sync.dismiss(); + syncApks(); + restoreSelectedView(); + } + }); + } + else{ + Toast.makeText(getActivity(),"google drive is not connected",Toast.LENGTH_SHORT).show(); + mGoogleApiClient.connect(); + } + } + else{ + Toast.makeText(getActivity(),"Please sign in to upload",Toast.LENGTH_SHORT).show(); + } + + + break; + case R.id.action_share: ArrayList selectedPositions = mAdapter.getSelectedPositions(); @@ -503,5 +541,33 @@ public void closeSearch() { } + /** + * @brief Calls the async task to sync the apk to drive sequentially + */ + public void syncApks() { + ArrayList selectedPositions = mAdapter.getSelectedPositions(); + if (selectedPositions.size() == 1) { + Toast.makeText(activity, "Uploading Apk", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(activity, "Uploading Apk's", Toast.LENGTH_SHORT).show(); + } + + for (int selectedPosition : selectedPositions) { + SavedApi apk = savedApis.get(selectedPosition); + File file = new File(apk.getFile().getPath()); + + String [] strings =new String[4]; + + strings[0]=file.getName(); + strings[1]= String.valueOf(selectedPosition); + strings[2]=String.valueOf(APK_CATEGOTY); + strings[3]=file.getPath(); + + new UploadFileTask().execute(strings); + + } + } + + } diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadProjectFragment.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadProjectFragment.java index ab3f7d52..a4df7647 100644 --- a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadProjectFragment.java +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/LoadProjectFragment.java @@ -37,6 +37,7 @@ import org.buildmlearn.toolkit.constant.Constants; import org.buildmlearn.toolkit.model.SavedProject; import org.buildmlearn.toolkit.model.Template; +import org.buildmlearn.toolkit.service.UploadFileTask; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.xml.sax.SAXException; @@ -51,12 +52,15 @@ import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import static org.buildmlearn.toolkit.activity.HomeActivity.mGoogleApiClient; + /** * @brief Fragment used for loading existing projects into a list. */ public class LoadProjectFragment extends Fragment implements AbsListView.OnItemClickListener { private static final String TAG = "Load Project Fragment"; + private static final int SAVED_PROJECT_CATEGOTY = 2; private AbsListView mListView; private boolean showTemplateSelectedMenu; @@ -68,6 +72,7 @@ public class LoadProjectFragment extends Fragment implements AbsListView.OnItemC private boolean isSearchOpened = false; private EditText editSearch; + public static int semaphore = 1; /** * {@inheritDoc} @@ -378,6 +383,45 @@ public void onClick(View v) { } }); break; + + case R.id.action_sync_saved_project: + + + if(mGoogleApiClient != null){ + if(mGoogleApiClient.isConnected()) { + + final AlertDialog dialog_sync = new AlertDialog.Builder(activity) + .setTitle("Sync to Drive") + .setMessage("Do you want to save the selected projects to your drive") + .setPositiveButton(R.string.dialog_yes, null) + .setNegativeButton(R.string.dialog_no, null) + .create(); + + dialog_sync.show(); + + dialog_sync.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dialog_sync.dismiss(); + syncProjects(); + restoreSelectedView(); + } + }); + } + else{ + + Toast.makeText(getActivity(),"Drive not connected",Toast.LENGTH_SHORT).show(); + mGoogleApiClient.connect(); + } + } + else{ + + Toast.makeText(getActivity(),"Drive not connected",Toast.LENGTH_SHORT).show(); + } + + + break; + case R.id.action_share: ArrayList selectedPositions = mAdapter.getSelectedPositions(); @@ -394,6 +438,7 @@ public void onClick(View v) { sendIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); startActivity(Intent.createChooser(sendIntent, null)); break; + case R.id.action_search: isSearchOpened = true; @@ -544,4 +589,33 @@ public void closeSearch() { } } + + + /** + * Calls the asyc task to sync the project to drive sequentially + */ + public void syncProjects() { + ArrayList selectedPositions = mAdapter.getSelectedPositions(); + if (selectedPositions.size() == 1) { + Toast.makeText(activity, "Uploading Project", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(activity, "Uploading Projects", Toast.LENGTH_SHORT).show(); + } + + for (int selectedPosition : selectedPositions) { + + SavedProject project =savedProjects.get(selectedPosition); + File file = new File(project.getFile().getPath()); + + String [] strings =new String[4]; + + strings[0]=file.getName(); + strings[1]= String.valueOf(selectedPosition); + strings[2]=String.valueOf(SAVED_PROJECT_CATEGOTY); + strings[3]=file.getPath(); + + new UploadFileTask().execute(strings); + + } + } } diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/SettingsFragment.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/SettingsFragment.java index 4dca9b73..47ce35d4 100644 --- a/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/SettingsFragment.java +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/fragment/SettingsFragment.java @@ -33,6 +33,7 @@ /** * Created by abhishek on 21/06/15 at 9:51 PM. */ + public class SettingsFragment extends PreferenceFragment { private static final int REQUEST_PICK_APK = 9985; diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/service/MyDriveEventService.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/service/MyDriveEventService.java new file mode 100644 index 00000000..739de5f5 --- /dev/null +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/service/MyDriveEventService.java @@ -0,0 +1,109 @@ +package org.buildmlearn.toolkit.service; + +/** + * Created by iit2014094 on 2/19/2017. + */ + +import android.app.NotificationManager; +import android.content.Context; +import android.media.RingtoneManager; +import android.net.Uri; +import android.support.v4.app.NotificationCompat; +import android.util.Log; + +import com.google.android.gms.drive.Drive; +import com.google.android.gms.drive.DriveFile; +import com.google.android.gms.drive.DriveId; +import com.google.android.gms.drive.DriveResource; +import com.google.android.gms.drive.Metadata; +import com.google.android.gms.drive.events.CompletionEvent; +import com.google.android.gms.drive.events.DriveEventService; + +import org.buildmlearn.toolkit.R; + + +import static org.buildmlearn.toolkit.activity.HomeActivity.mGoogleApiClient; +import static org.buildmlearn.toolkit.fragment.LoadProjectFragment.semaphore; + +/** + * Created by iit2014094 on 2/15/2017. + */ + +public class MyDriveEventService extends DriveEventService { + + /** + * oncompletion method is called upon completion of sync of each apk/project or on failure of sync + */ + @Override + public void onCompletion(CompletionEvent event) { + Log.d("TAG", "Action completed with status: " + event.getStatus()); + + if (event.getStatus() == CompletionEvent.STATUS_SUCCESS) { + + DriveId driveId = event.getDriveId(); + DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, driveId); + DriveResource.MetadataResult result = file.getMetadata(mGoogleApiClient).await(); + if (!result.getStatus().isSuccess()) { + + semaphore++; + event.dismiss(); + return; + } + Metadata metadata = result.getMetadata(); + + Log.d("TAGGG","Metadata succesfully fetched. Title: " + metadata.getTitle()); + + Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.activated_background) + .setSound(uri) + .setContentTitle(metadata.getTitle()) + .setContentText("Successfully synced with drive"); + + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + mNotificationManager.notify((int) (Math.random()*255), mBuilder.build()); + semaphore++; + + } + + if (event.getStatus() == CompletionEvent.STATUS_FAILURE) { + + + + DriveId driveId = event.getDriveId(); + DriveFile file = Drive.DriveApi.getFile(mGoogleApiClient, driveId); + DriveResource.MetadataResult result = file.getMetadata(mGoogleApiClient).await(); + if (!result.getStatus().isSuccess()) { + event.dismiss(); + return; + } + Metadata metadata = result.getMetadata(); + + Log.d("TAGGG","Metadata succesfully fetched. Title: " + metadata.getTitle()); + + Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + + NotificationCompat.Builder mBuilder = + new NotificationCompat.Builder(this) + .setSmallIcon(R.drawable.activated_background) + .setSound(uri) + .setContentTitle(metadata.getTitle()) + .setContentText("failed to sync with drive"); + + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + mNotificationManager.notify((int) (Math.random()*255), mBuilder.build()); + + semaphore ++; + return ; + + } + + event.dismiss(); + } +} diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/service/UploadFileTask.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/service/UploadFileTask.java new file mode 100644 index 00000000..fc5190a7 --- /dev/null +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/service/UploadFileTask.java @@ -0,0 +1,214 @@ +package org.buildmlearn.toolkit.service; + +import android.os.AsyncTask; +import android.support.annotation.NonNull; +import android.util.Log; + +import com.google.android.gms.common.api.ResultCallback; +import com.google.android.gms.drive.Drive; +import com.google.android.gms.drive.DriveApi; + +import com.google.android.gms.drive.DriveFile; +import com.google.android.gms.drive.DriveFolder; +import com.google.android.gms.drive.DriveId; +import com.google.android.gms.drive.ExecutionOptions; +import com.google.android.gms.drive.MetadataChangeSet; +import com.google.android.gms.drive.query.Filters; +import com.google.android.gms.drive.query.Query; +import com.google.android.gms.drive.query.SearchableField; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import static org.buildmlearn.toolkit.activity.HomeActivity.mGoogleApiClient; + +/** + * Created by iit2014094 on 2/20/2017. + */ + +public class UploadFileTask extends AsyncTask{ + + private DriveFile driveFile; + private String path,nameOfFile; + + + @Override + protected Void doInBackground(String... strings) { + + nameOfFile = strings[0]; + path =strings[3]; + + + Query query = new Query.Builder() + .addFilter(Filters.eq(SearchableField.TITLE,strings[0])) + .build(); + + Drive.DriveApi.query(mGoogleApiClient, query) + .setResultCallback(metadataCallback); + + return null; + } + + /** + * Handles whether to create a new apk/saved project/draft in the google drive or update the already persent apk/saved project/draft + */ + private ResultCallback metadataCallback = + new ResultCallback() { + @Override + public void onResult(@NonNull DriveApi.MetadataBufferResult metadataBufferResult) { + if (!metadataBufferResult.getStatus().isSuccess()) { + Log.d("TAG","No internet connection"); + return ; + } + + int results = metadataBufferResult.getMetadataBuffer().getCount(); + + //if apk /saved project/draft is already present in drive + if (results > 0) { + + DriveId driveId = metadataBufferResult.getMetadataBuffer().get(0).getDriveId(); + driveFile = driveId.asDriveFile(); + + //open the drivefile and call to result callback to update it + driveFile.open(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null) + .setResultCallback(driveContentsCallback); + + } + //if apk / saved file/draft is not present in the drive + else if(results == 0){ + + //call to result callback to create new apk /new saved project/new draft in the drive + Drive.DriveApi.newDriveContents(mGoogleApiClient) + .setResultCallback(newContentsCallback); + } + } + }; + + /** + * updates the already exisiting apk/saved project/draft in the drive + */ + + private ResultCallback driveContentsCallback = + new ResultCallback() { + @Override + public void onResult(@NonNull DriveApi.DriveContentsResult driveContentsResult) { + if (!driveContentsResult.getStatus().isSuccess()) { + driveFile.open(mGoogleApiClient, DriveFile.MODE_WRITE_ONLY, null) + .setResultCallback(driveContentsCallback); + return; + } + + OutputStream outputStream = driveContentsResult.getDriveContents().getOutputStream(); + + try { + + File tempFile = new File(path); + byte[] bytefile =readFile(tempFile); + outputStream.write(bytefile); + + } catch (IOException e) { + e.printStackTrace(); + } + + //get notification after completion of sync of apk/saved project/draft + ExecutionOptions executionOptions = new ExecutionOptions.Builder() + .setNotifyOnCompletion(true) + .build(); + + //sync the apk/saved project/draft with the drive + driveContentsResult.getDriveContents().commit(mGoogleApiClient, null, executionOptions) + .setResultCallback(new ResultCallback() { + @Override + public void onResult(@NonNull com.google.android.gms.common.api.Status status) { + Log.d("TAG","onresult callback recieved"); + + } + }); + + } + + /** + * converts the given file data into byte array and returns it + */ + + private byte[] readFile(File file) throws IOException { + + ByteArrayOutputStream ous = null; + InputStream ios = null; + try { + byte[] buffer = new byte[400096]; + ous = new ByteArrayOutputStream(); + ios = new FileInputStream(file); + int read; + while ((read = ios.read(buffer)) != -1) { + ous.write(buffer, 0, read); + } + } finally { + try { + if (ous != null) + ous.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + try { + if (ios != null) + ios.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return ous.toByteArray(); + } + }; + + /** + * creates new apk/draft/saved project in the drive and initializes its contents to null + * + */ + + private ResultCallback newContentsCallback = + new ResultCallback() { + @Override + public void onResult(@NonNull DriveApi.DriveContentsResult driveContentsResult) { + + if (!driveContentsResult.getStatus().isSuccess()) { + return; + } + + Log.d("TAG","sucessful recieving of drive contents"); + + + //providing metadata for the new apk /saved project/draft + MetadataChangeSet changeSet = new MetadataChangeSet.Builder() + .setTitle(nameOfFile) + .setMimeType("*/*") + .build(); + + + //create the new apk /saved project/draft without data + Drive.DriveApi.getRootFolder(mGoogleApiClient) + .createFile(mGoogleApiClient, changeSet, null) + .setResultCallback(new ResultCallback() { + @Override + public void onResult(@NonNull DriveFolder.DriveFileResult driveFileResult) { + Log.d("TAG","New File Succesfully created"); + } + }); + + + //build the query for the apk /saved project/draft + Query query = new Query.Builder() + .addFilter(Filters.eq(SearchableField.TITLE,nameOfFile)) + + .build(); + + //query the drive again for the apk/draft/saved project + Drive.DriveApi.query(mGoogleApiClient, query).setResultCallback(metadataCallback); + } + }; +} diff --git a/source-code/app/src/main/java/org/buildmlearn/toolkit/utilities/CircleTransform.java b/source-code/app/src/main/java/org/buildmlearn/toolkit/utilities/CircleTransform.java new file mode 100644 index 00000000..7b001d56 --- /dev/null +++ b/source-code/app/src/main/java/org/buildmlearn/toolkit/utilities/CircleTransform.java @@ -0,0 +1,48 @@ +package org.buildmlearn.toolkit.utilities; + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.squareup.picasso.Transformation; + + +/** + * Created by iit2014094 on 2/10/2017. + */ +public class CircleTransform implements Transformation { + + @Override + public Bitmap transform(Bitmap source) { + int size = Math.min(source.getWidth(), source.getHeight()); + + int x = (source.getWidth() - size) / 2; + int y = (source.getHeight() - size) / 2; + + Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); + if (!(squaredBitmap.equals(source))) { + source.recycle(); + } + + Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); + + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); + BitmapShader shader = new BitmapShader(squaredBitmap, + BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); + paint.setShader(shader); + paint.setAntiAlias(true); + + float r = size / 2f; + canvas.drawCircle(r, r, r, paint); + + squaredBitmap.recycle(); + return bitmap; + } + + @Override + public String key() { + return "circle"; + } +} diff --git a/source-code/app/src/main/res/drawable-hdpi/google_login.png b/source-code/app/src/main/res/drawable-hdpi/google_login.png new file mode 100644 index 00000000..a717d61a Binary files /dev/null and b/source-code/app/src/main/res/drawable-hdpi/google_login.png differ diff --git a/source-code/app/src/main/res/drawable-hdpi/upload.png b/source-code/app/src/main/res/drawable-hdpi/upload.png new file mode 100644 index 00000000..8533d7b3 Binary files /dev/null and b/source-code/app/src/main/res/drawable-hdpi/upload.png differ diff --git a/source-code/app/src/main/res/drawable-mdpi/google_login.png b/source-code/app/src/main/res/drawable-mdpi/google_login.png new file mode 100644 index 00000000..d0334af7 Binary files /dev/null and b/source-code/app/src/main/res/drawable-mdpi/google_login.png differ diff --git a/source-code/app/src/main/res/drawable-mdpi/upload.png b/source-code/app/src/main/res/drawable-mdpi/upload.png new file mode 100644 index 00000000..5f1929e1 Binary files /dev/null and b/source-code/app/src/main/res/drawable-mdpi/upload.png differ diff --git a/source-code/app/src/main/res/drawable-xhdpi/google_login.png b/source-code/app/src/main/res/drawable-xhdpi/google_login.png new file mode 100644 index 00000000..804c71d3 Binary files /dev/null and b/source-code/app/src/main/res/drawable-xhdpi/google_login.png differ diff --git a/source-code/app/src/main/res/drawable-xhdpi/upload.png b/source-code/app/src/main/res/drawable-xhdpi/upload.png new file mode 100644 index 00000000..38319749 Binary files /dev/null and b/source-code/app/src/main/res/drawable-xhdpi/upload.png differ diff --git a/source-code/app/src/main/res/drawable-xxhdpi/google_login.png b/source-code/app/src/main/res/drawable-xxhdpi/google_login.png new file mode 100644 index 00000000..273d232f Binary files /dev/null and b/source-code/app/src/main/res/drawable-xxhdpi/google_login.png differ diff --git a/source-code/app/src/main/res/drawable-xxhdpi/upload.png b/source-code/app/src/main/res/drawable-xxhdpi/upload.png new file mode 100644 index 00000000..1043e1d7 Binary files /dev/null and b/source-code/app/src/main/res/drawable-xxhdpi/upload.png differ diff --git a/source-code/app/src/main/res/layout/listview_header_navigation_drawer.xml b/source-code/app/src/main/res/layout/listview_header_navigation_drawer.xml index a3422881..8b652fc0 100644 --- a/source-code/app/src/main/res/layout/listview_header_navigation_drawer.xml +++ b/source-code/app/src/main/res/layout/listview_header_navigation_drawer.xml @@ -13,6 +13,7 @@ android:src="@drawable/bg_navigation_drawer_header" /> + android:id="@+id/nav_text" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true"> + android:textSize="@dimen/sub_title" + android:gravity="center"/> - \ No newline at end of file diff --git a/source-code/app/src/main/res/menu/menu_apk_selected.xml b/source-code/app/src/main/res/menu/menu_apk_selected.xml index 0e42d42a..50d2eecb 100644 --- a/source-code/app/src/main/res/menu/menu_apk_selected.xml +++ b/source-code/app/src/main/res/menu/menu_apk_selected.xml @@ -3,10 +3,17 @@ xmlns:tools="http://schemas.android.com/tools" tools:context="org.buildmlearn.toolkit.fragment.LoadProjectFragment"> + + @@ -20,7 +27,7 @@ @@ -28,7 +35,7 @@ diff --git a/source-code/app/src/main/res/menu/menu_project_selected.xml b/source-code/app/src/main/res/menu/menu_project_selected.xml index 0e42d42a..2f0e1f41 100644 --- a/source-code/app/src/main/res/menu/menu_project_selected.xml +++ b/source-code/app/src/main/res/menu/menu_project_selected.xml @@ -3,24 +3,31 @@ xmlns:tools="http://schemas.android.com/tools" tools:context="org.buildmlearn.toolkit.fragment.LoadProjectFragment"> + + @@ -28,7 +35,7 @@ diff --git a/source-code/app/src/main/res/menu/nav_drawer.xml b/source-code/app/src/main/res/menu/nav_drawer.xml index 0b33648b..4595d1f3 100644 --- a/source-code/app/src/main/res/menu/nav_drawer.xml +++ b/source-code/app/src/main/res/menu/nav_drawer.xml @@ -48,6 +48,11 @@ android:icon="@drawable/menu_info" android:title="@string/menu_about_us" android:visible="true" /> + diff --git a/source-code/build.gradle b/source-code/build.gradle index 18cedec8..592d656a 100644 --- a/source-code/build.gradle +++ b/source-code/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' - + classpath 'com.google.gms:google-services:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/source-code/gradle.properties b/source-code/gradle.properties index 74d56b1f..1c860c5a 100644 --- a/source-code/gradle.properties +++ b/source-code/gradle.properties @@ -13,3 +13,4 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sat Jan 14 09:01:08 IST 2017 +