Android で よくある正規表現を使えるやつ

そもそもは Linkify のWEBリンクがなんだかな, と思い.

device-2011-08-23-153643

使えそうなよくある正規表現がいくつか用意されていたのですな.

public static final Pattern WEB_URL = Pattern.compile(
    "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
  + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
  + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
  + "(?:" + DOMAIN_NAME + ")"
  + "(?:\\:\\d{1,5})?)"
  + "(\\/(?:(?:[" + GOOD_IRI_CHAR + "\\;\\/\\?\\:\\@\\&\\=\\#\\~"
  + "\\-\\.\\+\\!\\*\\'\\(\\)\\,\\_])|(?:\\%[a-fA-F0-9]{2}))*)?"
  + "(?:\\b|$)");
public static final Pattern PHONE
  = Pattern.compile(                
      "(\\+[0-9]+[\\- \\.]*)?"      
    + "(\\([0-9]+\\)[\\- \\.]*)?"   
    + "([0-9][0-9\\- \\.]+[0-9])"); 
public static final Pattern EMAIL_ADDRESS
  = Pattern.compile(
    "[a-zA-Z0-9\\+\\.\\_\\%\\-\\+]{1,256}" +
    "\\@" +
    "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}" +
    "(" +
        "\\." +
        "[a-zA-Z0-9][a-zA-Z0-9\\-]{0,25}" +
     ")+"
  );

platform_frameworks_base/Patterns.java

すぐにそのまま使おう.


if (Patterns.WEB_URL.matcher(text).find()) {
  // do something
}

「厳格なのか?」でフィルターをつける場合.

// A match filter that only accepts odd numbers.
MatchFilter oddFilter = new MatchFilter() {
    public final boolean acceptMatch(CharSequence s, int start, int end) {
        int n = Character.digit(s.charAt(end-1), 10);
        return (n & 1) == 1;
    }
};

// Match all digits in the pattern but restrict links to only odd
// numbers using the filter.
Pattern pattern = Pattern.compile("[0-9]+");
Linkify.addLinks(text, pattern, "http://...", oddFilter, null);

Android Text Links Using Linkify


Android Data Binding は いつ実力を発揮できるのだ?!

Data_Binding_Guide___Android_Developers

Data Binding Guide | Android Developers

たくさん記事を見かけるようになったのでかんたんに比較してみようかと思い.

20160104-195007

これまで

public class MainActivity extends AppCompatActivity {

  private TextView name;
  private TextView age;

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

    name = (TextView) findViewById(R.id.name);
    age = (TextView) findViewById(R.id.age);

    User user = new User("ジョーンズ", 30);

    name.setText(user.name);
    age.setText(String.valueOf(user.age));
  }

  public void onClickName(View v) {
    Toast.makeText(this, " 名前をクリックしました。", Toast.LENGTH_SHORT).show();
  }

}
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickName"
        />
    <TextView
        android:id="@+id/age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
 </LinearLayout>

ButterKnife

dependencies {
 	...
    compile 'com.jakewharton:butterknife:7.0.1'
}
public class MainActivity extends AppCompatActivity {

  @Bind(R.id.name) TextView name;
  @Bind(R.id.age) TextView age;

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

    ButterKnife.bind(this);

    User user = new User("ジョーンズ", 30);

    name.setText(user.name);
    age.setText(String.valueOf(user.age));
  }

  @OnClick(R.id.name)
  public void onClickName(View v) {
    Toast.makeText(this, " 名前をクリックしました。", Toast.LENGTH_SHORT).show();
  }

}
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <TextView
        android:id="@+id/age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
 </LinearLayout>

Data Binding

android {
	...
    dataBinding {
        enabled = true
    }
}
public class MainActivity extends AppCompatActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MainActivityBinding binding = 
         DataBindingUtil.setContentView(this, R.layout.main_activity);

    User user = new User("ジョーンズ", 30);

    binding.setUser(user);
    binding.setActivity(this);
  }

  public void onClickName(View v) {
    Toast.makeText(this, " 名前をクリックしました。", Toast.LENGTH_SHORT).show();
  }

}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.example.User"/>
        <variable
            name="activity"
            type="com.example.MainActivity" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.name}"
            android:onClick="@{activity.onClickName}"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{String.valueOf(user.age)}"
            />
    </LinearLayout>
</layout>

むむむ...

レイアウトを繰り返し使うような ListView/RecyclerView で実力を発揮するのかな?

This is more than binding simple data to your views and avoiding the boilerplate code. To me, this is actually mixing business logic in your UI layouts. Your views should be as dumb as possible, adhering to the Single Responsibility Principle with the only responsibility to show data. This could lead to a complicated, cluttered and unclean codebase.

We've seen some of the examples of the Data Binding API. I'm sure that this API was created in order to ease the developers' work and avoid boilerplate, but one can overuse it and accidentally create chaos in his code. Mixing Java in your view code has never been a good idea. Does JSP ring a bell?

How you can go wrong with the new Data Binding API

強力な分だけ「用法・用量」に注意, ということなのか.

ちなみに AndroidStudio最新環境では build.gradle 内 dataBinding { enabled = true } のみで使えるようになっておる.

Data Binding Guide | Android Developers


Mac OS X ファイル名の濁点を変換 (PHP)

OSによってファイル名の正規化が行われる.

UAX15-NormFig3

Unicode正規化 - Wikipedia

Linux / Windows
NFC: Normalization Form Canonical Compression

OS X
NFD: Normalization Form Canonical Decompression

異なる「正規化」間で問題となる.

PHPで認識して変換できるのか.

ファイルを OSX上でつくる.

$ ls
KONBU.txt        こんふ.txt       こんぶ.txt

これに対してPHPコード.

<?php
$files = glob('*.txt');
foreach ($files as $key => $file) {
    $raw = pathinfo($file, PATHINFO_FILENAME);
    $nfc_iconv = iconv('UTF-8-MAC', 'UTF-8', $raw);
  //$nfc_normalizer = Normalizer::normalize($raw, Normalizer::FORM_C);
    echo $raw                                  . "\t" .
         mb_strlen($raw, 'UTF-8')              . "\t" . 
       //mb_strlen($raw, 'UTF-8-MAC')          . "\t" . 
         iconv_strlen($raw, 'UTF-8-MAC')       . "\t" .
         urlencode($raw)                       . "\n";
    echo $nfc_iconv                            . "\t" .
         mb_strlen($nfc_iconv, 'UTF-8')        . "\t" . 
         iconv_strlen($nfc_iconv, 'UTF-8-MAC') . "\t" .
         urlencode($nfc_iconv)                 . "\n";
  //echo $nfc_normalizer                       . "\n";
}

実行.

$ php test.php 
KONBU	5	5	KONBU
KONBU	5	5	KONBU
こんふ	3	3	%E3%81%93%E3%82%93%E3%81%B5
こんふ	3	3	%E3%81%93%E3%82%93%E3%81%B5
こんぶ	4	3	%E3%81%93%E3%82%93%E3%81%B5%E3%82%99
こんぶ	3	3	%E3%81%93%E3%82%93%E3%81%B6

よって, NFDからNFCに変換する場合.

iconv('UTF-8-MAC', 'UTF-8', $raw)

PHP関数 iconv*( ) は「UTF-8-MAC」を知っている.


今ではToolbar記述は不要となっていました とさ

昔々, こんな記述がありました.

...
dependencies {
    compile "com.android.support:appcompat-v7:21.0.+"
}
...
...
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.blah);

    Toolbar toolbar = (Toolbar) findViewById(R.id.myawesometoolbar);
    setSupportActionBar(toolbar);
}
...
...
<android.support.v7.widget.Toolbar
    android:id=”@+id/my_awesome_toolbar”
    android:layout_height=”wrap_content”
    android:layout_width=”match_parent”
    android:minHeight=”?attr/actionBarSize”
    android:background=”?attr/colorPrimary” />
...

AppCompat v21 — Lollipop 搭載前のデバイスにマテリアル デザインを! - Google Developer Japan Blog

旧ActionBarを隠したりとか, そんなテーマのとか, メニューのとか, 面倒でしたが今ではもうこの記述不要なのですね.

以下, Android Studio で BlankActivity をGUIから作成. API23.

...
dependencies {
    ...
    compile 'com.android.support:appcompat-v7:23.0.1'
}
...
...
public class MainActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
}
...
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
...
>
    <TextView
        android:text="Hello World!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</RelativeLayout>

KITKATでもLOLLIPOPでもきちんと表示されます.
Android_Device_Monitor 2

Android_Device_Monitor

テーマは, 非NoActionBarを親にして色を設定.

...
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>
...

前の記述のままでも動いてしまうのですが, 消したほうが気持ちがよいです.

元々,「appcompat-v7」の「v7」というのは,「API7まで対応できる」という後方互換の意味でしたよね.


日本で使える LTE/3G バンド は?

IMEI制限などあるのかもしれないけれど, 国内でフツーにLTE受信できる端末なのかどうか.

今や海外産のスマホが多くなってきてなんだかわかりづらい

最近の発売端末のそこらをみてみる.

Nexus5X

UMTS/WCDMA: B1/2/4/5/6/8/9/19
LTE (FDD): B1/2/3/4/5/7/8/9/17/18/19/20/26/28

Nexus 5X - Fingerprint Scanner - LG - Nexus - Android Phones - Google Store

Nexus6P

UMTS/WCDMA: B1/2/4/5/6/8/9/19
LTE (FDD): B1/2/3/4/5/7/8/9/17/19/20/28

Nexus 6P - Solid Metal Frame - Huawei - Nexus - Android Phones - Google Store

iPhone6s

Model A1633*
LTE (Bands 1, 2, 3, 4, 5, 7, 8, 12, 13, 17, 18, 19, 20, 25, 26, 27, 28, 29, 30)

Model A1688*
LTE (Bands 1, 2, 3, 4, 5, 7, 8, 12, 13, 17, 18, 19, 20, 25, 26, 27, 28, 29)

iPhone 6s - Technical Specifications - Apple

Wikipedia でみてみるがややこしい...

List_of_LTE_networks_-_Wikipedia__the_free_encyclopedia

List of LTE networks - Wikipedia, the free encyclopedia

総務省公開の資料をみる.

www_soumu_go_jp_main_content_000361981_pdf

総務省|テレコム競争政策ポータルサイト|各携帯電話事業者の通信方式と周波数帯について

各端末のスペック表に合わせて見やすく整形しておく.

LTEバンド一覧

まあ, ショップで店員さんに聞けば済むっちゃあ済む.