WebViewとは?

Webviewとは?
-> HTMLコンテンツをアプリ内で見れるようにすること
-> SafariやChromeで見られる枠組みをアプリ内に作ることができる
-> HTMLの更新をすれば良いので、アプリストアへの申請や審査、アップデートは必要ない
-> iOS, AndroidともにWebviewに対応している
-> ユーザ体験、操作性はネイティブアプリの方が優れている
-> 全てをWebviewにするのではなく、ヘッダ、フッタの調整などを行うことが多い
-> Webブラウザのレンダリングエンジンを呼び出しているが、ブラウザ自体を起動している訳ではない。そのため、設定やCookieなどは別で管理される

アプリ(Webview)のメリット・デメリット
– push通知を送信できる
– ネイティブを開発するよりも開発・運用コストを抑制できる
– Webとの違いを出しずらい

### Android
– Android System Webview
1.GUIコンポーネントのWebviewを使用する

<WebView
android:id=”@+id/webView″
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:layout_alignParentLeft=”true” />

2. マニュフェストにインターネットアクセスを許可するパーミッション追加
3. インクをクリックしたときに標準ブラウザを起動しないようにする

WebView myWebView = (WebView) findViewById(R.id.webView);
myWebView.setWebViewClient(new WebViewClient());
myWebView.loadUrl(“https://www.google.com/”);

### iOS
– SFSafariView、WKWebView、(UIWebView(非推奨))などを使う
UIApplication classを使う

import UIKit
 
class ViewController: UIViewController , UIWebViewDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = URL(string: "https://hoge.com/")!
        
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(url)
        }
        
    }
}

SFSafariViewController

import UIKit
import SafariServices
 
class ViewController: UIViewController {
 
    override func viewDidLoad() {
        super.viewDidLoad()
 
    }
 
    override func viewDidAppear(_ animated: Bool) {
        let webPage = "https://hoge.com/"
        let safariVC = SFSafariViewController(url: NSURL(string: webPage)! as URL)
        present(safariVC, animated: true, completion: nil)
    }
}

Cleanup

Open storage area
– Delete unnecessary files that waste space and free up space for what you need.

– Delete unnecessary file such as cache, temporary files, residual data from your Android device or app
– See which apps occupy the most space
– Identify and delete apps you no longer use

Crash Report

What is a crash report?

When an error occurs in the application, it may be terminated, but the terminal stores the information inside the terminated application at that time.

The screen will be displayed at the end, but if you tap the report, the development team can use the information for defect correction.

The crash report contains the following information, but does not contain personally identifying information.
– App version
– Android version
– Device type
– Error occurrence time
– Error occurrence point
– Number of occurrences
– Message you entered

ドコモの「アプリクラッシュポート」についてを見てみましょう
アプリクラッシュレポート

Certificate and Key Store

A public key certificate, also called an electronic or identity certificate, contains a public key consisting of a public / private key pair, as well as other metadata (such as name and location) that identify the owner of the key. The certificate owner also owns the corresponding private key.

When you sign the APK, the signing tool attaches a public key certificate to the APK. The same is true if you signed the app bundle. A public key certificate acts as “fingerprint” that uniquely associates an APK or app bundle with the owner and the corresponding private key. This will allow Android to verify that subsequent app updates are genuine and have been released by the original author. The key used to create this certificate is called the app signing key.

A keystore is a binary file that contains one or more private keys. In order to allow users to install new versions as app updates, all apps must use the same certificate throughout the usage period.

activity_main xml

<?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:orientation="vertical"
    android:background="#ffaa88"
    tools:context=".MainActivity">

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/word"/>
        <EditText
            android:id="@+id/uriname"
            android:inputType="text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal" >
        <Button
            adnroid:id="@+id/post"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:text="@string/post" />
        <Button
            android:id="@+id/browser"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"
            android:text="@string/browser" />
    </LinearLayout>

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

Android Studioでdependencyを追加する。

file -> project structure を押す

dependency -> libraries dependency を選択する

dependenciesが追加される。

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    implementation 'org.jdom:jdom2:2.0.6'
}

rss parse

package com.capital.anew;

import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private Handler handler;
    private final String RSS_URL = "http://m-shige1979.hatenablog.com/rss";
    private TextView text1;
    private String RssText;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler = new Handler();
        setContentView(R.layout.activity_main);
        text1 = (TextView)findViewById(R.id.textview1);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu){

        MenuItem item1 = menu.add("UPDATE");
        item1.setIcon(android.R.drawable.ic_menu_upload);

        item1.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener(){
            @Override
            public boolean onMenuItemClick(MenuItem item){

                Thread thread1 = new Thread(){
                    @Override
                    public void run(){
                        try {
                            RssText = RssParse.getRss(MainActivity.this, RSS_URL);

                            handler.post(new Runnable(){
                                @Override
                                public void run(){
                                    text1.setText(RssText);
                                    Toast.makeText(MainActivity.this, "読み込み終了", Toast.LENGTH_SHORT).show();

                                }
                            });
                        } catch (Exception e){
                            Log.d("sample", e.getMessage());
                        }
                    }
                };
                thread1.start();
                return false;
            }
        });

        item1.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);

        getMenuInflater().inflate(R.menu.menu_main, menu);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item){
        int id = item.getItemId();

        if(id == R.id.action_settings){
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

}

package com.capital.anew;

import android.content.Context;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class parse {
public static String getRss(Context context, String url)
throws IOException {

StringBuilder sb = new StringBuilder();

AndroidHttpClient client = AndroidHttpClient.newInstance(“TEST”);
HttpGet get = new HttpGet(url);

try {
HttpResponse response = client.execute(get);

BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line = null;
while((line = br.readLine()) != null){
sb.append(line);
}
} finally {
client.close();
}
return sb.toString();
}
}
[/code]

android unresolved dependencies error when creating a new project

エラーログに記載のdependenciesを修正する

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:26.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

Gradle Build Runningがやけに時間がかかる。

そもそもandroid sdkとは?
Android SDK【Android Software Development Kit】
Android OSを搭載したスマートフォンやタブレット端末で動作するプログラムを開発するために必要なソフトウェアをひとまとめにしたパッケージで、コンパイラやデバッガ、ライブラリ、デバイスドライバ、ドキュメント、サンプルコード、パソコン上で端末を再現するエミュレータなどで構成される。

constraint-layout:1.1.2を1.1.0にしたらエラーが消えた。1.1.2は新しいversionだから、新しすぎると駄目なのか。Gradle build finished. 謎だ。

implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'

Android Studioでのapkファイルの開き方

file -> Profile or debug APK… で開く

どうりで、file -> New で何度やってもダメだった訳だ。

debugしようとすると、”please select Android SDK”のエラー

SDK、moduleをセットして、外部androidに接続する。

OK、APKの課題はクリアーした。意外と簡単だった。
androidは、次はjsonだが、その前に、git、grep、dream weaverをやらないといけない。