顯示具有 App inventor 標籤的文章。 顯示所有文章
顯示具有 App inventor 標籤的文章。 顯示所有文章

2022年6月10日 星期五

App inventor:透過Google Apps Script 使用google sheets資料(新增資料)

 App inventor可透過web 這個網路元件積木,連接至Google Apps Script,而後透過其中的功能讀取、新增、更新Google Sheet的資料。大概的步驟如下:

一、於google網路硬碟中,依你的需要新增一個Google Sheet,以下例子檔名設為test,資料表中只加入了ID及NAME作示範。如下:




二、於google網路硬碟中,開一個Google Apps script作為中介的網站。

(2-1)


(2-2)寫法如下:



//外部程式若使用get方法連接google apps scipt,會自動去尋找doGet()這個函數,並執行裡頭的方程式,e為傳進來的參數總集合
function doGet(e) {
//宣告ss變數為連接test資料表這個方法,後面那個為test那個google sheet的網址
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1ZqgyZd4D12P3NRI7_db5g5BFLOC46FEPB_k278S754g/edit#gid=0");
//宣告sheet為取得 工作表1
var sheet = ss.getSheetByName("工作表1");
//執行adduser這個下面自寫的函數
adduser(e,sheet);

}
//外部程式若使用post方法連接google apps scipt,會自動去尋找doPost(e)這個函數,並執行裡頭的方程式,e為傳進來的參數總集合
function doPost(e) {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1ZqgyZd4D12P3NRI7_db5g5BFLOC46FEPB_k278S754g/edit#gid=0");
//宣告sheet為取得 工作表1
var sheet = ss.getSheetByName("工作表1");
//執行adduser這個下面自寫的函數
adduser(e,sheet);

}

//因為上面那個方法都有使用到以下的方法,因此在這裡寫了一個adduser的函數
function adduser(e,sheet){
//取得傳過來參數總集合裡id的值(傳過來的那個id值)
var id = e.parameter.id;
//取得傳過來參數總集合裡name的值(傳過來的那個id值)
var name = e.parameter.name;
//將資料加入
sheet.appendRow([id,name]);
}


(2-3)點選「布署」「 新增布署畫面」「選取類型」「網頁應用程式」,最後做如下的設定後按「布署」。

(2-4)把發布後的網頁應用程式網址複製下來,等會要在App inventor用到。

三、開啟App inventor,並依你的需求製作介面。以下簡單的製作可以輸入id和name的輸入盒,及送出按鈕一個。介面如下:




(3-1)積木拉法如下:網址為剛才布置後的「網頁應用程式網址」

四,接下來運作APP,輸入id和name,就可以在剛才的test資料庫中看到加入的資料。



參考:https://www.oxxostudio.tw/articles/201805/backend-apps-script.html

           https://ai2.metricrat.co.uk/guides/post-data-to-a-google-sheet


2022年5月8日 星期日

App inventor:aix檔練習3,取得網路資料。

 import android.app.Activity;

import android.content.Context;
import com.google.appinventor.components.annotations.*;
import com.google.appinventor.components.common.ComponentCategory;
import com.google.appinventor.components.runtime.AndroidNonvisibleComponent;
import com.google.appinventor.components.runtime.ComponentContainer;
import com.google.appinventor.components.runtime.EventDispatcher;

import com.google.appinventor.components.runtime.AndroidViewComponent;
import android.view.View;
import android.graphics.Bitmap;
import java.io.FileOutputStream;
import android.graphics.Bitmap.CompressFormat;
import android.content.pm.PackageManager;

import java.net.CookieHandler;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.SocketTimeoutException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;

import android.os.Environment;
import java.io.File;
import com.google.appinventor.components.runtime.util.AsynchUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.HttpURLConnection;
import java.net.URLConnection;

@DesignerComponent(
version = 1,
description = "",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "")

@SimpleObject(external = true)
//Libraries
@UsesLibraries(libraries = "")
//Permissions
@UsesPermissions(permissionNames = "android.permission.INTERNET"+"android.permission.ACCESS_NETWORK_STATE")

public class TA extends AndroidNonvisibleComponent {

//Activity and Context
private Context context;
private Activity activity;

public TA(ComponentContainer container){
super(container.$form());
this.activity = container.$context();
this.context = container.$context();
}

@SimpleFunction(description = "Sample Function Generated by Niotron")
public void WebsiteContent(final String website) {
AsynchUtil.runAsynchronously(new Runnable() { // Always do get request Asynchronously
@Override
public void run() {
try {
URL url = new URL(website);
URLConnection urlConnection = url.openConnection();
HttpURLConnection connection = null;
if(urlConnection instanceof HttpURLConnection)
{
connection = (HttpURLConnection) urlConnection;
}
else
{
}
BufferedReader readStream = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
// BufferedReader的作用在於用串流的方式讀取資料的,URL()可連接網頁.openStream是它的一種連接方法
String readLine; // 宣告讀取的變數資料名為readLine
StringBuilder data = new StringBuilder(); // 這結果的資將建立於此
//當資料不為空的時間,就將新的資料readLine存到 data這個變數的最後
while (( readLine = readStream.readLine() ) != null)
data.append(readLine); // Read all the lines from the readStream
readStream.close(); //關掉這個readStream
final String finalData = data.toString(); // 將findaData轉為String型態
activity.runOnUiThread(new Runnable() { // Always raise events on UI thread
@Override
public void run() {
//取得資料後,傳到Event中執行
myEvent(finalData); // You're event with data
}
});
} catch (IOException e) {
e.printStackTrace(); // Error occured
}
}
});
}

@SimpleEvent(description = "Test Event Generated by Niotron")
public void myEvent(String Data){
EventDispatcher.dispatchEvent(this, "myEvent",Data);
}
}



參考網頁:https://juejin.cn/post/6844903970649931783



2022年5月6日 星期五

App inventor:aix程式碼與積木顏色對應說明

aix檔中程式透過@後的裝飾符來判斷執行那項功能,會出現那一種顏色的積木


一、當裝飾符為@SimpleFunction,會出現紫色的積木,範例 如下:

@SimpleFunction(description = "Takes a screenshot of the current app, with the given quality, compressFormat and saves the screenshot as the given path.")
public void TakeScreenshot(int quality, String compressFormat, String path) {
}


TakeScreenshot為function的名稱,quality, compressFormat 及path為可傳入的參數。

二、當裝飾符為@SimpleProperty,會出現淺綠色或是緣色的積木,範例 如下:
//設定屬性,回傳JPEG
@SimpleProperty(description = "A compress format block.")
public String Jpeg() {
return "JPEG";
}

沒有參數時出現淺綠色

@SimpleProperty(description = "A compress format block.")
public String Jpeg(int a) {
return "JPEG";
}
有參數時出現深綠色



三、當裝飾符為@SimpleEvent,會出現橘色的積木,範例 如下:
@SimpleEvent(description = "This event is fired when the extension has taken the screenshot in the given path.")
public void SavedScreenshot (String path) {
EventDispatcher.dispatchEvent(this, "SavedScreenshot", path);
}


四、當裝飾符為@DesignerProperty,會出現在ui設定頁面,範例 如下:


@DesignerProperty(editorType = DesignerProperty.PROPERTY_TYPE_COLOR,
defaultValue = Component.DEFAULT_VALUE_COLOR_BLACK)
@SimpleProperty
public void PaintColor(int argb) {
paintColor = argb;
changePaint(paint, argb);
}

@DesignerProperty要放在@SimpleProperty前:

editorType = DesignerProperty.PROPERTY_TYPE_COLOR 的類型為PROPERTY_TYPE_COLOR
defaultValue = Component.DEFAULT_VALUE_COLOR_BLACK 預設值為Component.DEFAULT_VALUE_COLOR_BLACK
editorTye 類型參考 點我
defaultvalue類型參考 點我



其它:

@DesignerComponent(
version = 1,
description = "",
category = ComponentCategory.EXTENSION,
nonVisible = true,
iconName = "")
設定此程式的基本資訊

version = 1 版本
description = "" 程式描述
category 擴充自什麼包
nonVisible = true 不顯示於ui介面
iconName = "" 程式小圖位址

@SimpleObject(external = true)
//Libraries
@UsesLibraries(libraries = "okhttp-3.6.0.jar.jar"+"okio-2.8.0.jar"+"okhttp-urlconnection-3.10.0")
//Permissions
@UsesPermissions(permissionNames = "android.permission.INTERNET")

UsesLibraries 可透過右下角的Libraries按鍵加入你的包,再加在上面
UsesPermissions 為要要求的權限

App inventor 2 透過web元件連接firebase(7):透過Realtime Database資料庫進行資料處理(第三種權限設定)

 一、範例二( 透過此設定「經過身份驗證的使用者都只可以讀取但只有自己才可以寫入自己uid下的資料夾內容。」)

(一)權限設定的方法如下:以下權限設在專案下 user/$uid/password_activity的資料夾中

(1)".read": "auth.uid != null", 只要localID不為空就可以read

(2) ".write": "$uid === auth.uid",此行是說$uid此資料夾名稱與登入者的localID相同才能寫入

{ "rules": { ".read": "false", ".write": "false", "user": { "$uid": { "password_activity":{ ".read": "auth.uid != null", ".write": "$uid === auth.uid", }, } } } }

(二)App Inventor 2方法

1.拉出web元件
(1)web元件連接的網址如下:
https://<DATABASE_NAME>.firebaseio.com/user/$uid/password_activity/.json

[PROJECT_ID]是你專案的編號

user/$uid/password_activity/.json 是你讀取資料的位置,你權限設能讀取那裡就寫那裡。

說明一:ID_TOKEN為登入給予的令牌,在你登入firebase後,會回傳給予你這個值。
跟之前完全不用權限的方法不同,就只有多了要給予下面的參數值,若沒有給予這個<ID_TOKEN>,它會告知你沒有足夠的權限存取。
說明二:這跟前面那個傳值的方法是完全相同的,但因為你在firebase裡權限只限可以讀取的範圍在
https://<DATABASE_NAME>.firebaseio.com/user/$uid/password_activity中,因此你若想寫入其它的資料夾,它不會讓你寫入。因此你要確定你的路徑是正確的。

大致的作法如下,這次先從建立資料開始,建立一個user下資料夾跟系統每次給你的uid(localId)相同名字的。在登入的時候,系統的回傳值,除了Idtoken外,還會有localID,而這個localld就是上面的$uid。因此你在登入後,需將Idtoken和 localld先存在清單中,以便以後可以再繼續使用。像下面這個圖。

(1)post

(2)put



   (3)get

(4)patch

(5)del



參考資料:

App inventor 2 透過web元件連接firebase(6):透過Realtime Database資料庫進行資料處理(第二種權限設定)

 firebase有很多設定權限的方法,可參考此網址或此網址,這裡只示範兩種:

一、範例一( 透過此設定「經過身份驗證的使用者都可以讀取和寫入您的完整資料庫。」)

(一)權限設定的方法如下:

{ "rules": { ".read": "auth.uid != null", ".write": "auth.uid != null" } }


(二)App Inventor 2方法

1.拉出web元件
(1)web元件連接的網址如下:
https://<DATABASE_NAME>.firebaseio.com/name.json?auth=<ID_TOKEN>

[PROJECT_ID]是你專案的編號

name.json 是你讀取資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中

ID_TOKEN為登入給予的令牌,在你登入firebase後,會回傳給予你這個值。
跟之前完全不用權限的方法不同,就只有多了要給予下面的參數值,若沒有給予這個<ID_TOKEN>,它會告知你沒有足夠的權限存取。


大致的作法如下:
(1)get
(2)post



(3)put


(4)patch



(5)del


上述做完後,都會回傳資料。可利用web元件的另一個積木做後續的處理。如下範例:



App inventor 2 透過web元件連接firebase(5):透過Realtime Database資料庫進行資料處理(第一種權限設定)

 一、需開啟firebase讀寫的的權限,以下先以全部人都可以讀寫示範。

二、get put post del說明

(一)讀取資料-get方法

1.拉出web元件

(1)web元件連接的網址如下:https://[PROJECT_ID].firebaseio.com/name.json

[PROJECT_ID]是你專案的編號
name.json 是你讀取資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中
大致的作法如下:

傳送完,會給回傳值資料為 json型態,如下:
{ "first": "Jack", "last": "Sparrow" }
可再用web元件中的json解析,將資料解析成一般資料

(二)新增資料-post方法

1.拉出web元件

(1)web元件連接的網址如下:https://[PROJECT_ID].firebaseio.com/name.json

[PROJECT_ID]是你專案的編號
name.json 是你新增資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中
大致的作法如下:要注意的是那個post的文字,需要是json格式,否則會報錯:
例:{ "first": "Jack", "last": "Sparrow" }



注意:post方法會為你新增的資料再新增一個亂數的資料以新增新的資料。


(三)更新資料-put方法(不可個別更新,會全部覆蓋)

1.拉出web元件

(1)web元件連接的網址如下:https://[PROJECT_ID].firebaseio.com/name.json

[PROJECT_ID]是你專案的編號
name.json 是你更新資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中
大致的作法如下:要注意的是那個post的文字,需要是json格式,否則會報錯:
例:{ "first": "Jack", "last": "Sparrow" }





注意:put的更新方法,是將你資料夾下的資料,更新成現在你傳上去的資料,因此原有的資料會全部不見。要千萬注意。

(四)更新資料-patch方法(可更新資料夾中的個別資料)

1.拉出web元件

(1)web元件連接的網址如下:https://[PROJECT_ID].firebaseio.com/name.json

[PROJECT_ID]是你專案的編號
name.json 是你更新資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中
大致的作法如下:要注意的是那個post的文字,需要是json格式,否則會報錯:
例:{ "first": "Jack", "last": "Sparrow" }
若要單獨更新first的資料,則patch的文字就傳送{ "first": "Jack2"},會將名字更新為Jack2

(五)刪除資料-del方法

1.拉出web元件

(1)web元件連接的網址如下:https://[PROJECT_ID].firebaseio.com/name.json

[PROJECT_ID]是你專案的編號
name.json 是你刪除資料的位置,依你存在那裡進行調整,所以可能是
https://[PROJECT_ID].firebaseio.com/xxx.json 存在專案的xxx資料夾中
https://[PROJECT_ID].firebaseio.com/user/xxx.json 存在專案的user/xxx資料夾中
大致的作法如下:要注意的是那個post的文字,需要是json格式,否則會報錯:
例:{ "first": "Jack", "last": "Sparrow" }
參考資料:https://firebase.google.com/docs/reference/rest/database





App inventor 2 透過web元件連接firebase(4):傳送電郵,確認所使用的信箱是否為本人所有。

 一、拉一個web元件

二、web元件連接的網址如下:

https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=[API_KEY]

此[API_KEY]有三個部份

1.firebase中的專案管理中的 網路 API 金鑰的內容,如下:



2.requestType  回傳 requestType=PASSWORD_RESET

3.e-mail  你的e-mail,當註冊完,系統的回傳值中,會有email。

完整的內容為:

https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=金鑰&requestType=PASSWORD_RESET&email=你的e-mail

一般此確認信件會在確認註冊完成後立即寄出,作法如下:(註冊成功後的那部份)