After so many experiments finally got this solution. Many of you asked this from so many days. first regret for late post, but Happy to present this experiment before You.. Make the best of the resource.
Note :
- This is like simple prototype, and based on this try to design and develop your own applications.
- Whole code contains simple work flow, I have reduced image quality in the code before upload.
[maxbutton id=”5″ url=”https://github.com/androidLabsCode/GsheetAsDbWithImageUpload” ]
- APP SCRIPT
function doGet(e) { var op = e.parameter.action; if(op=="insert") return insert_value(e); if(op=="readAll") return read_all_value(e); } function doPost(e) { var op = e.parameter.action; if(op=="insert") return insert_value(e); if(op=="readAll") return read_all_value(e); } var SCRIPT_PROP = PropertiesService.getScriptProperties(); // see: https://developers.google.com/apps-script/reference/properties/ /** * select the sheet */ function setup() { var doc = SpreadsheetApp.getActiveSpreadsheet(); SCRIPT_PROP.setProperty("key", doc.getId()); } function insert_value(e) { var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key")); var sheet = doc.getSheetByName('sheet1'); // select the responses sheet var uId = e.parameter.uId; var uName= e.parameter.uName; var uImage = e.parameter.uImage; var dropbox = "USERS IMAGE"; var folder, folders = DriveApp.getFoldersByName(dropbox); if (folders.hasNext()) { folder = folders.next(); } else { folder = DriveApp.createFolder(dropbox); } var fileName = uId+uName+"profile_pic.jpg"; var contentType = "image/jpg", bytes = Utilities.base64Decode(uImage), blob = Utilities.newBlob(bytes, contentType,fileName); var file = folder.createFile(blob); file.setSharing(DriveApp.Access.ANYONE_WITH_LINK,DriveApp.Permission.VIEW); var fileId=file.getId(); var fileUrl = "https://drive.google.com/uc?export=view&id="+fileId; sheet.appendRow([uId,uName,fileUrl]); return ContentService.createTextOutput("Success").setMimeType(ContentService.MimeType.JAVASCRIPT); } function read_all_value(request){ var ss =SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key")); var output = ContentService.createTextOutput(), data = {}; //Note : here sheet is sheet name , don't get confuse with other operation var sheet="sheet1"; data.records = readData_(ss, sheet); var callback = request.parameters.callback; if (callback === undefined) { output.setContent(JSON.stringify(data)); } else { output.setContent(callback + "(" + JSON.stringify(data) + ")"); } output.setMimeType(ContentService.MimeType.JAVASCRIPT); return output; } function readData_(ss, sheetname, properties) { if (typeof properties == "undefined") { properties = getHeaderRow_(ss, sheetname); properties = properties.map(function(p) { return p.replace(/\s+/g, '_'); }); } var rows = getDataRows_(ss, sheetname), data = []; for (var r = 0, l = rows.length; r < l; r++) { var row = rows[r], record = {}; for (var p in properties) { record[properties[p]] = row[p]; } data.push(record); } return data; } function getDataRows_(ss, sheetname) { var sh = ss.getSheetByName(sheetname); return sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getValues(); } function getHeaderRow_(ss, sheetname) { var sh = ss.getSheetByName(sheetname); return sh.getRange(1, 1, 1, sh.getLastColumn()).getValues()[0]; }
2. Android Part
Step 1: Create a new android Project
Step 2: Add required libraries in Gradle files. Add in app level Gradle file
1.Volley Library for network handling functionalities
2.Picasso Library to display images
........ compile 'com.android.volley:volley:1.0.0' compile 'com.squareup.picasso:picasso:2.5.2' ......... .........
Step 3: Add following layout files which are used in app
1.Go to Layouts –> Replace code in activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="alabs.gsheetwithimage.MainActivity" tools:layout_editor_absoluteY="81dp" tools:layout_editor_absoluteX="0dp" > <Button android:id="@+id/btn_add_user" android:layout_width="105dp" android:layout_height="50dp" android:text="Add User" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" app:layout_constraintRight_toRightOf="parent" android:layout_marginTop="140dp" tools:layout_constraintLeft_creator="1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.501" android:background="#4286f4"/> <Button android:id="@+id/btn_list_user" android:layout_width="105dp" android:layout_height="50dp" android:text="View Users" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" app:layout_constraintRight_toRightOf="parent" android:layout_marginTop="52dp" app:layout_constraintTop_toBottomOf="@+id/btn_add_user" tools:layout_constraintLeft_creator="1" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintHorizontal_bias="0.501" android:background="#4286f4"/> </android.support.constraint.ConstraintLayout>
2. Go to Layouts –> create new Layout add_user.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:id="@+id/et_uid" android:layout_width="0dp" android:layout_height="49dp" android:ems="10" android:inputType="textPersonName" android:hint="User ID" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="16dp" tools:layout_constraintRight_creator="1" app:layout_constraintRight_toRightOf="@+id/et_uname" tools:layout_constraintLeft_creator="1" app:layout_constraintLeft_toLeftOf="@+id/et_uname" /> <EditText android:id="@+id/et_uname" android:layout_width="308dp" android:layout_height="47dp" android:ems="10" android:inputType="textPersonName" android:hint="User Name" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintBottom_creator="1" app:layout_constraintBottom_toTopOf="@+id/iv_uphoto" android:layout_marginEnd="26dp" app:layout_constraintRight_toRightOf="parent" android:layout_marginTop="80dp" android:layout_marginBottom="81dp" app:layout_constraintTop_toTopOf="@+id/et_uid" android:layout_marginRight="26dp" /> <Button android:id="@+id/btn_image" android:layout_width="0dp" android:layout_height="48dp" android:layout_marginEnd="56dp" android:layout_marginLeft="56dp" android:layout_marginRight="56dp" android:layout_marginStart="56dp" android:layout_marginTop="162dp" android:text="Add Image" android:background="#4286f4" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintTop_creator="1" /> <ImageView android:id="@+id/iv_uphoto" android:layout_width="0dp" android:layout_height="0dp" app:srcCompat="@mipmap/ic_launcher" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintBottom_creator="1" android:layout_marginStart="67dp" app:layout_constraintBottom_toBottomOf="@+id/btn_add_user" android:layout_marginEnd="67dp" android:layout_marginTop="62dp" tools:layout_constraintLeft_creator="1" android:layout_marginBottom="53dp" app:layout_constraintTop_toTopOf="@+id/btn_image" android:layout_marginLeft="67dp" android:layout_marginRight="67dp" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintVertical_bias="0.0" /> <Button android:id="@+id/btn_add_user" android:layout_width="203dp" android:layout_height="48dp" android:layout_marginBottom="27dp" android:text="Add User" android:background="#4286f4" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="0.502" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" /> </android.support.constraint.ConstraintLayout>
3. Go to Layouts –> create new Layout user_list.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/list_view" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="8dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" tools:layout_constraintBottom_creator="1" tools:layout_constraintLeft_creator="1" tools:layout_constraintRight_creator="1" tools:layout_constraintTop_creator="1" /> </android.support.constraint.ConstraintLayout>
4. Go to Layouts –> create new Layout list_row.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout_editor_absoluteY="81dp" tools:layout_editor_absoluteX="0dp"> <TextView android:id="@+id/tv_uid" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:textColor="#111111" android:textSize="20dp" tools:layout_constraintTop_creator="1" tools:layout_constraintRight_creator="1" app:layout_constraintRight_toRightOf="parent" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toTopOf="@+id/imageView3" app:layout_constraintLeft_toRightOf="@+id/imageView3" android:layout_marginTop="7dp" android:layout_marginLeft="8dp" app:layout_constraintHorizontal_bias="0.098" /> <TextView android:id="@+id/tv_uname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" android:textColor="#646566" android:textSize="25dp" tools:layout_constraintTop_creator="1" android:layout_marginTop="14dp" app:layout_constraintTop_toBottomOf="@+id/tv_uid" tools:layout_constraintLeft_creator="1" app:layout_constraintLeft_toLeftOf="@+id/tv_uid" /> <ImageView android:id="@+id/imageView3" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginStart="32dp" app:srcCompat="@drawable/logo_icon" app:layout_constraintRight_toLeftOf="@+id/tv_uname" android:layout_marginRight="8dp" android:layout_marginLeft="32dp" app:layout_constraintLeft_toLeftOf="parent" tools:layout_constraintTop_creator="1" android:layout_marginEnd="8dp" android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.0" /> </android.support.constraint.ConstraintLayout>
Step 4 : Add Java classes
- Add AddUser.java class which adds the user to Spread Sheet
package alabs.gsheetwithimage; /** * Created by ADJ on 8/7/2017. */ import android.app.ProgressDialog; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.util.Base64; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import com.android.volley.DefaultRetryPolicy; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.RetryPolicy; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; import static alabs.gsheetwithimage.Configuration.ADD_USER_URL; import static alabs.gsheetwithimage.Configuration.KEY_ACTION; import static alabs.gsheetwithimage.Configuration.KEY_ID; import static alabs.gsheetwithimage.Configuration.KEY_IMAGE; import static alabs.gsheetwithimage.Configuration.KEY_NAME; public class AddUser extends AppCompatActivity implements View.OnClickListener { private EditText editTextUserName; private EditText editTextUserId; private ImageView imageViewUserImage; private Button buttonAddUser,buttonAddImage; String userImage; private int PICK_IMAGE_REQUEST = 1; Bitmap rbitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.add_user); editTextUserId = (EditText) findViewById(R.id.et_uid); editTextUserName = (EditText) findViewById(R.id.et_uname); imageViewUserImage=(ImageView)findViewById(R.id.iv_uphoto); buttonAddUser = (Button) findViewById(R.id.btn_add_user); buttonAddImage = (Button) findViewById(R.id.btn_image); buttonAddImage.setOnClickListener(this); buttonAddUser.setOnClickListener(this); } public Bitmap getResizedBitmap(Bitmap image, int maxSize) { int width = image.getWidth(); int height = image.getHeight(); float bitmapRatio = (float)width / (float) height; if (bitmapRatio > 1) { width = maxSize; height = (int) (width / bitmapRatio); } else { height = maxSize; width = (int) (height * bitmapRatio); } return Bitmap.createScaledBitmap(image, width, height, true); } public String getStringImage(Bitmap bmp) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos); byte[] imageBytes = baos.toByteArray(); String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT); return encodedImage; } private void addUser(){ final ProgressDialog loading = ProgressDialog.show(this,"Uploading...","Please wait...",false,false); final String userId = editTextUserId.getText().toString().trim(); final String userName = editTextUserName.getText().toString().trim(); //Bitmap rbitmap = getResizedBitmap(bitmap,500); Log.e("null","values"+userImage); StringRequest stringRequest = new StringRequest(Request.Method.POST,ADD_USER_URL, new Response.Listener<String>() { @Override public void onResponse(String response) { loading.dismiss(); Toast.makeText(AddUser.this,response,Toast.LENGTH_LONG).show(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(AddUser.this,error.toString(),Toast.LENGTH_LONG).show(); } }){ @Override protected Map<String,String> getParams(){ Map<String,String> params = new HashMap<String, String>(); params.put(KEY_ACTION,"insert"); params.put(KEY_ID,userId); params.put(KEY_NAME,userName); params.put(KEY_IMAGE,userImage); return params; } }; int socketTimeout = 30000; // 30 seconds. You can change it RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT); stringRequest.setRetryPolicy(policy); RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(stringRequest); } private void showFileChooser() { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) { Uri filePath = data.getData(); try { //Getting the Bitmap from Gallery Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), filePath); rbitmap = getResizedBitmap(bitmap,250);//Setting the Bitmap to ImageView userImage = getStringImage(rbitmap); imageViewUserImage.setImageBitmap(rbitmap); } catch (IOException e) { e.printStackTrace(); } } } @Override public void onClick(View v) { if(v == buttonAddUser){ addUser(); } if(v == buttonAddImage){ showFileChooser(); } } }
- Add UserList.java class, which list the users in Spread Sheet
package alabs.gsheetwithimage; /** * Created by ADJ on 8/8/2017. */ import android.app.ProgressDialog; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.widget.ListView; import android.widget.Toast; import com.android.volley.DefaultRetryPolicy; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.RetryPolicy; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.android.volley.toolbox.Volley; import static alabs.gsheetwithimage.Configuration.LIST_USER_URL; public class UserList extends AppCompatActivity { private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.user_list); listView = (ListView) findViewById(R.id.list_view); sendRequest(); } private void sendRequest(){ final ProgressDialog loading = ProgressDialog.show(this,"Uploading...","Please wait...",false,false); StringRequest stringRequest = new StringRequest(LIST_USER_URL, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.e("null","ser image"+response); showJSON(response); loading.dismiss(); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(UserList.this,error.getMessage(),Toast.LENGTH_LONG).show(); } }); int socketTimeout = 30000; // 30 seconds. You can change it RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT); stringRequest.setRetryPolicy(policy); RequestQueue requestQueue = Volley.newRequestQueue(this); requestQueue.add(stringRequest); } private void showJSON(String json){ JsonParser pj = new JsonParser(json); pj.parseJSON(); Log.e("uImage","ser image"+JsonParser.uImages[1]); UserListAdapter userListAdapter = new UserListAdapter(this, JsonParser.uIds,JsonParser.uNames,JsonParser.uImages); listView.setAdapter(userListAdapter); } }
- Add UserListAdapter.java class, which helps in listing the users in UserList.java class
package alabs.gsheetwithimage; /** * Created by ADJ on 8/8/2017. */ import android.app.Activity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; public class UserListAdapter extends ArrayAdapter<String> { private String[] uId; private String[] uNames; private String[] uImages; private Activity context; public UserListAdapter(Activity context, String[] uId, String[] uNames, String[] uImages) { super(context, R.layout.list_row, uId); this.context = context; this.uId = uId; this.uNames = uNames; this.uImages = uImages; } @Override public View getView(int position, View convertView, ViewGroup parent) { LayoutInflater inflater = context.getLayoutInflater(); View listViewItem = inflater.inflate(R.layout.list_row, null, true); TextView textViewId = (TextView) listViewItem.findViewById(R.id.tv_uid); TextView textViewName = (TextView) listViewItem.findViewById(R.id.tv_uname); ImageView iv = (ImageView)listViewItem.findViewById(R.id.imageView3); textViewId.setText(uId[position]); textViewName.setText(uNames[position]); // Uri uri = Uri.parse(uImages[position]); //Uri uri = Uri.parse("https://drive.google.com/uc?id=0B___GhMLUVtOY09SbDU5cDU2T1U"); // draweeView.setImageURI(uri); Picasso.with(context).load(uImages[position]).into(iv); return listViewItem; } }
- Add JsonParser.java class, which parse the Json response sent from server side through app script, Spread sheet
package alabs.gsheetwithimage; /** * Created by ADJ on 8/9/2017. */ import android.util.Log; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import static alabs.gsheetwithimage.Configuration.KEY_ID; import static alabs.gsheetwithimage.Configuration.KEY_IMAGE; import static alabs.gsheetwithimage.Configuration.KEY_NAME; import static alabs.gsheetwithimage.Configuration.KEY_USERS; public class JsonParser { public static String[] uIds; public static String[] uNames; public static String[] uImages; private JSONArray users = null; private String json; public JsonParser(String json){ this.json = json; } protected void parseJSON(){ JSONObject jsonObject=null; try { jsonObject = new JSONObject(json); users = jsonObject.getJSONArray(KEY_USERS); uIds = new String[users.length()]; uNames = new String[users.length()]; uImages = new String[users.length()]; for(int i=0;i<users.length();i++){ JSONObject jo = users.getJSONObject(i); uIds[i] = jo.getString(KEY_ID); uNames[i] = jo.getString(KEY_NAME); uImages[i] = jo.getString(KEY_IMAGE); } Log.e("uImage","ser image"+uImages[0]); } catch (JSONException e) { e.printStackTrace(); } } }
- Add MainActivity.java class, which starts the activity and display the buttons to add and view users.
package alabs.gsheetwithimage; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { Button addUser,viewUser; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); addUser=(Button)findViewById(R.id.btn_add_user); viewUser=(Button)findViewById(R.id.btn_list_user); addUser.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getApplicationContext(),AddUser.class); startActivity(intent); } }); viewUser.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getApplicationContext(),UserList.class); startActivity(intent); } }); } }
- Add Configuration.java class, which contains url, attributes and parameters
package alabs.gsheetwithimage; /** * Created by ADJ on 8/9/2017. */ public class Configuration { public static final String APP_SCRIPT_WEB_APP_URL = "ADD YOUR APP SCRIPT WEB APP URL"; public static final String ADD_USER_URL = APP_SCRIPT_WEB_APP_URL; public static final String LIST_USER_URL = APP_SCRIPT_WEB_APP_URL+"?action=readAll"; public static final String KEY_ID = "uId"; public static final String KEY_NAME = "uName"; public static final String KEY_IMAGE = "uImage"; public static final String KEY_ACTION = "action"; public static final String KEY_USERS = "records"; }
Step 5 : Add Manifest file
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="alabs.gsheetwithimage"> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".AddUser"/> <activity android:name=".UserList"/> </application> </manifest>
Step 6 : Run the App and check the results
Hi,
Have HTML PART for receive,update and delete images?
Thank you
Will update soon
Can you please help me?
Thank you
Hi. Thanks for the tutorial. I got this working too. There was no typo although I had to delete the /u/o from my generated url from the app script. I also changed “Sheet1” to “sheet1” in my spreadsheet to match the code. What’s the next tutorial? Can you make something that use firebase, google spreadsheet, and google maps api that tracks location? thanks again!
In my app there are two spinners whose items come from google spreadsheet and spinners are dependent each other. How can i do this. Pls help
Hello,
Love the idea with this i am getting a volley server error and think this is due to the g-script not functioning correctly as it does not run in GS without returning an error. any ideas?
kind regards
TypeError: Cannot read property “parameter” from undefined. (line 3, file “Code”)
where to write app script?
uploaded data is not display. Please suggest why its not working and share me app code on lakhanjharia@gmail.com as soon as possible. thankyou