2016年6月29日 星期三

Android 元件 (Google App Engine) 建置雲端跟App互動(二)

Google App Engine(二)

上一篇: Android 元件 (Google App Engine) 建置雲端跟App互動(一)

本章運用到了:

MVC設計模式
Adapter接配線模式
BaseAdapter
ListView的 ViewHolider概念

本章目的:
1.在資料庫中 建立『資料表』,查詢『資料表』
2.『查詢』功能 下一篇 Google App Engine(三)
3.『新增』、『刪除』、『變更』功能 完全互動 下一篇Google App Engine(四)

GAE (AddServlet)

目的:在資料庫中建立資料表
位置:後台建立 (app中 第三篇再提到)


Step1:新增Libraries

(A) 將jar檔 添加到App_cloud_backend,libs的資料夾
載點:點我下載JDK ,或Google下載


(B) 將jar檔 添加道專案中






(C) 添加成功,到App_cloud_backend,build中 會成功顯示下圖↓




Step2:建立AddServlet的Class(App_cloud_backend)

(A) 用途目的:新增資料

註冊

name=  類別名稱
class= 類別存放詳細的位置
url-pattent= 在url中需要輸入什麼找到他,很重要!! (因為每一個類 都有自己所對應的)
Myservlet 對應的是→ /hello
Addservlet 對應的是→ /add
Queryservlet 對應的是→ /query (待會)




(B) 開始撰寫AddServlet程式碼
JAVA:AddServlet
package com.example.myapplication.backend;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import java.io.IOException;
import java.util.Date;
import java.util.Random;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class AddServlet extends HttpServlet {
   @Override
   public void doGet(HttpServletRequest req, HttpServletResponse resp)
           throws IOException {

       resp.setContentType("text/plain");

       //使用工廠獲取 DatastoreService
       DatastoreService ds = DatastoreServiceFactory.getDatastoreService();

       //創建一個資料表 name= book
       Entity book = new Entity("Book");

       //資料表 放入資料
       book.setProperty("title", "android");
       book.setProperty("author", "Vincent");
       book.setProperty("price", new Random().nextInt(500) + 500);
       book.setProperty("time", new Date().getDate());

       //放入資料表
       //DatastoreService對象並調用put方法寫入數據 
       ds.put(book);
      
       //有點類似 JAVA的System.out.print("") 打印出訊息
       resp.getWriter().println("add ok");
   }
}


(C) 先執行模擬器,完成後再Build。




(D)Build,訊息出現Successfully代表成功
注意每一個專案後面的數字都是專屬且隨機賦予的
因為google提供的免費試用是有額度限制的,
所以一旦超出額度限制就會產生錯誤, 請務必用自己產生的可避免錯誤

(E) 到網路上確認是否沒問題,注意:網址後面要改成 /add
可以看出剛剛java撰寫打印出訊息 resp.getWriter().println("add ok");

補充:為什麼網址要改成 /add ? 因為註冊的是/add




Step3:找尋資料表

(A) 增加了資料,我們就會問說,那資料在哪裡呢?? 首先進到 Google Cloud Platform
(B) 我們會發現,重新整理一次網頁,Book資料表中的資料就會多新增一筆
(為了方便觀察,我們開啟兩個網頁觀察)








GAE (QueryServlet)

目的:查詢˙資料表
位置:後台建立 (app中 第三篇再提到)


Step1:建立QueryServlet的Class(App_cloud_backend)

(A) 用途目的:新增資料


(B) 文法賞析
(C) 撰寫程式
JAVA:QueryServlet
package com.example.myapplication.backend;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class QueryServlet extends HttpServlet {
    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {

        resp.setContentType("text/plain");

        DatastoreService ds = DatastoreServiceFactory.getDatastoreService();

        //查詢 資料表
        Query q = new Query("Book");

        for (Entity book : ds.prepare(q).asIterable()){
            resp.getWriter().println(book);
        }
    }
}


(D)到web.xml註冊,執行模擬器→Bulid一次→查看網頁是否成功(注意網址最後為 /query)
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">


  <!--定義servlet的name、servlet的class-->
  <servlet>
      <servlet-name>MyServlet</servlet-name>
      <servlet-class>com.example.myapplication.backend.MyServlet</servlet-class>
  </servlet>


  <!--mapping=外界要透過哪一個url讀取,所以一般來說我們都會在網址後方+ "/hello"-->


  <servlet-mapping>
      <servlet-name>MyServlet</servlet-name>
      <url-pattern>/hello</url-pattern>
  </servlet-mapping>


  <!--手動建立一個AddServlet-->
  <servlet>
      <servlet-name>AddServlet</servlet-name>
      <servlet-class>com.example.myapplication.backend.AddServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>AddServlet</servlet-name>
      <url-pattern>/add</url-pattern>
  </servlet-mapping>


<!--手動建立一個QueryServlet-->
  <servlet>
      <servlet-name>QueryServlet</servlet-name>
      <servlet-class>com.example.myapplication.backend.QueryServlet</servlet-class>
  </servlet>
  <servlet-mapping>
      <servlet-name>QueryServlet</servlet-name>
      <url-pattern>/query</url-pattern>
  </servlet-mapping>


  <!--<welcome-file-list>-->
  <!--沒有用到,我們就可以先刪除了-->
      <!--<welcome-file>index.html</welcome-file>-->
  <!--</welcome-file-list>-->


</web-app>




2016年6月27日 星期一

Android 元件 (Google App Engine) 建置雲端跟App互動(一) 延伸製作專屬的QRcode

Google App Engine(一)

本章目的:
1.基本的環境架設
2.建立資料庫
3.製作自己專屬的QRcode
4.製作資料庫中的『資料表』→Android 元件 (Google App Engine) 建置雲端跟App互動(二)
5.資料庫 與 App的互動→ 建設中

前言
一個應用程式若需要後台提供雲端訊息、資料儲存、查詢、運算時需要一個後台的資料庫,
Google App Engine for Java」服務是一個提供網頁系統執行的平台,簡稱為「GAE」,
與傳統的主機代管或是網頁代管不同的是,它提供了雲端服務的特色與資料儲存技術的優點,
可以降低初始成本,使用者不需要維護伺服器,只需要將網路應用程式上傳!!




首先大家要注意的是,google提供的免費的資料庫是有額度的
出現下列的訊息 1是額度用完、2是程式碼撰寫錯誤,尤其是在新增資料時最容易發生

所以文章內的網址最好是自己的google所創建的 不要引用內文的網址 才不會出現問題。



Step1:建立後台模組(backend)

(一)前置作業初始化


注意:Client module: 選擇對應的App(應用程式 前建立的model為 app_cloud)







Step2:檢查網址是否成功

(一)執行模擬器
 


(二)模擬器執行後,並點選網址查看。


(三)成功進入網址後,輸入一個id和網頁互動一下


(四)網頁 回應了你輸入的id



Step3:圖片上傳至網路

(一)先新增照片至→webapp(千萬不要複製錯地方) 記得把顯示的方式從Android→Project Files


(二)修改程式碼:


(原本)


(修改後) 上傳的格式為html,然後圖片格式。


JAVA:MyServlet
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
  resp.setContentType("text/html");
  resp.getWriter().println("<img src='bigmac.jpg'>");
}


(三)完成後再執行模擬器一次


(四)檢查圖片是否上傳成功,p.s:記得網址後面加上:   /hello

補充:為什麼是加hello 而不是其它的英文呢??

因為:
 




Step4:上傳至GAE



(一)登入你的GOOGLE帳號


(二)同意權限




(三)如果一開始沒有專案,點選【Click here】新增專案

(四)新增專案的name=cloud1




(五)新增後,即可點選專案



(六)確認以後,訊息出現 successfully即可連網看看。






Step5:查看網路

"輸入你專案的名稱." +”制式格式” + "/hello” 成功後如下圖!!!



Step6:製作QRcode





Step7:顯示至App



XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context="com.example.app_cloud.MainActivity">
<WebView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/webView"
         />




JAVA
package com.example.app_cloud;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;

public class MainActivity extends AppCompatActivity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);

       WebView webView = (WebView)findViewById(R.id.webView);
       webView.loadUrl("http://cloud1-1356.appspot.com/hello");

   }
}




下一篇:Android 元件 (Google App Engine) 建置雲端跟App互動(二)

2016年6月5日 星期日

Android 元件(Glide、GridView) 如何使用原生套件 下載JSON 的資料


心情小品:

禮拜五結束了貴公司的面試,忐忑不安的心理持續到了今天,
中午 人潮人海的休息時間 看的莫名感動,因為真希望我能成為裡面其中一份子
成為秉持著熱誠、專業、來服務客戶的一份子
相信只有努力練習是不會騙人的,為自己的人生努力,也未未來的公司多一份戰力
所以 美好的假日還是持續跟APP說 Hello囉 ^^。

如何使用第三方程式庫 Retrofit 下載Json資料(進入)

Android 元件 Glide、GridView

1.作業前準備:

Step1. Android Studio→先進行環境設定 加入網路權限

       詳細位置:Android Manifest
       程式碼:<uses-permission android:name="android.permission.INTERNET" />


Step2. Android Studio→先進行環境設定,並加入第三方程式庫

compile 'com.google.code.gson:gson:2.2.4'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.squareup.okhttp:okhttp:2.0.0'
詳細位置:設定→Plugins→搜尋"gsonformat"
使用介紹:能自動產生 對應到該頁面json格式 的類別


Step3. Android Studio→創造類別、Layout

詳細位置:Android Manifest
Class
AnimalBean (用來對應到網路上json格式用)
JsonAdapter (因為json沒有Adapter,所以我們要自己做一個Adapter)
Layout
Item.xml (用來顯示每筆資料用的item)

 Step4. 啟用google的擴充功能,使得網頁上Json的格式更清晰

             
工具都準備好了 我們開始來實現這個功能吧

2.Layout的布局:
Layout:activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   android:orientation="vertical"
   tools:context="com.example.andy.app_json.MainActivity">


   <GridView
       android:layout_width="match_parent"
       android:layout_height="432dp"
       android:id="@+id/gridView"
       android:layout_gravity="center_horizontal" />

</LinearLayout>

Layout:item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:weightSum="1">


  <ImageView
       android:adjustViewBounds="true"
       android:src="@drawable/w1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:id="@+id/iv_item"
        />
</LinearLayout>

3.完成對應網頁上json格式的類別:
詳細位置:Android Studio→java→Class→AnimailBean
使用介紹:利用外掛程式GsonFormat產生對應的類別,並存放在AnimalBean
簡單敘述:複製頁面上一筆資料,到android Studio中,
               
  快捷鍵 alt+insert 開啟外掛程式,並貼入,完整包覆後,按確認
Step1. 複製網頁上其中一筆json的資料

Step2. 貼入外掛程式中,點選需要的選項 完成(通常我都會一次選,以防日後所需)


4.開始建立連線 Step1. 建立連線
詳細位置:Android Studio→java→Class→MainActivity
簡單敘述:利用OKHTTP所提供的程式碼 GET A URL下載
                 並創立一個新的執行緒在背後運作,防止在下載工程卡死在頁面

java:MainActivity
package com.example.andy.app_json;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.GridView;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import java.io.IOException;

public class MainActivity extends AppCompatActivity {
   private Context context;
   private GridView gridView;
   private JsonAdapter adapter;

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       Initial();
       new RunWork().start();  
   }

   private void Initial() {
       context = this;
       gridView = (GridView) findViewById(R.id.gridView);
       //設定GridView的格式
       gridView.setNumColumns(3);
   }

   //內部類別 RunWork 繼承一個執行緒
   //RunWork 就是一個執行緒
   public class RunWork extends Thread {

       // step1.這段程式碼由OKhttp所提供
       // 分析 http 資料結構標準語法
       // Url是再把網址放入 這時候會發送 request方法給伺服器
      // 伺服器根據你要資料把資料用 response 回傳給你

       String json;
       OkHttpClient client = new OkHttpClient();
       String run(String url) throws IOException {
           Request request = new Request.Builder()
                   .url(url)
                   .build();
           Response response = client.newCall(request).execute();
           return response.body().string();
       }
     
       //step3:創造出step2所要的工作內容
       Runnable r = new Runnable() {


           @Override
           public void run() {
               adapter = new JsonAdapter(context,json);
               gridView.setAdapter(adapter);
               adapter.notifyDataSetChanged();
           }
       };

       //step2.
       // 運用OkHttp run的方法中,放入我們要讀取JSON的網址
       // 放入後再另一個排程, runOnUiThread(r),
       // runOnUiThread 就好像為了要持續改變 環境UI的方法
       // r就是工作的內容,這時候就要在new Runnable()出來。(上面)

 

       @Override
       public void run() {

           try {
               json = run("http://data.coa.gov.tw/Service/OpenData/AnimalOpenData.aspx?$top=500&$skip=0");
               runOnUiThread(r);
           } catch (IOException e) {
               e.printStackTrace();
           }        
       }
   }
}

3.創建Adapter Step1. 建立連線
詳細位置:Android Studio→java→Class→AnimalAdapter
簡單敘述: 因為Json沒有 Adapter,所以我們要繼承一個BaseAdapter使用

java:AnimalAdapter
package com.example.andy.app_json;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.gson.Gson;

public class JsonAdapter extends BaseAdapter{
   //《依賴》把需要用的東西都先宣告起來
   private Context context;
   private AnimalBean[] animalBeen;
   private ImageView m_iv_item;


   //建構子:記得創建方便使用
   public JsonAdapter(Context context , String json) {
       this.context = context;
       animalBeen=new Gson().fromJson(json,AnimalBean[].class);
   }

   @Override  //共有幾筆資料?
   public int getCount() {
       return animalBeen.length;
   }
   @Override     //取得資料的位置
   public Object getItem(int position) {
       return animalBeen[position];
   }
   @Override   //得到Item的ID
   public long getItemId(int position) {
       return position;
   }
   @Override   //設定資料
   public View getView(int position, View convertView, ViewGroup parent) {
       //因為item是一個xml,所以我們必須使用LayoutInflater(打氣筒),
       // 將這個item,inflate(打氣),然後膨脹展開這個頁面!
       View v = LayoutInflater.from(context).inflate(R.layout.item,parent,false);

       //膨脹以後我們就可以找到item的位置了
       m_iv_item=(ImageView)v.findViewById(R.id.iv_item);

       //使用Log日誌,來判斷是否下載資料了
       Test_Log_Data();

       String url = animalBeen[position].getAlbum_file();
       
//第三方程式庫 Glide 由google提供
//load:網址
//placeholder :下載失敗時要顯是什麼圖
//diskCacheStrategy :是否要存取以下載的
//into :顯示在哪邊?

      Glide.with(context)
               .load(url)
               .placeholder(R.drawable.w1)
               .diskCacheStrategy(DiskCacheStrategy.RESULT)
               .into(m_iv_item);

       return v;
   }

   private void Test_Log_Data(){
       for (int i=0; i<=animalBeen.length-1;i++) {
           Log.d("tag", "-------------" +(i+1) +"-------------");
           Log.d("tag", animalBeen[i].getAlbum_name().toString());
           Log.d("tag", animalBeen[i].getAnimal_colour().toString());
           Log.d("tag", animalBeen[i].getAnimal_place().toString());
           Log.d("tag", animalBeen[i].getAlbum_file().toString());
       }
   }
}

Step2.透過日誌來檢查資料的內容


我們來看看成果吧
相信大家看了以後才會知道RecyclerView的好用之處 對吧?
不然每次都要再找一次View,View都不會重複再利用 ,