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
+