hishidaの開発blog

EBシリーズ(EBPocket,EBWin,EBMac,EBStudio),KWIC Finder,xdoc2txt,読書尚友の開発者ブログ

「ランダムハウス英語辞典Toolkit」をEBStudio2で変換する場合の注意点

「ランダムハウス英語辞典Toolkit」で作成したHTMLが、EBStudio2では文字化けするという報告があった。旧EBStudioとは互換性を保っているはずなので、調査したところ、EBStudio2の新機能の「UnicodeからEPWING外字に自動登録する」が悪さをしていることがわかった。

ランダムハウス英語辞典Toolkit」では、文字の字下げを表現するために、EPWINGの制御文字(0x1F09)を直接16進コードで表現している箇所がある。

<dd><p>
[&#x00E9;i] a<br>
&#x1f09;&#x00;&#x02;━n.<br>
&#x1f09;&#x00;&#x02;(pl. A&apos;s or As, a&apos;s or as)<br>
&#x1f09;&#x00;&#x02;【1】英語アルファベットの第1字(母音字).<br>
&#x1f09;&#x00;&#x02;【2】A, a 字によって表される音[ei](bake),[&#xE0EC;](hat),[&#x0251;&#x02D0;](father),[&#x0254;&#x02D0;](small) など.<br>
&#x1f09;&#x00;&#x02;【3】A 字形の物.<br>
&#x1f09;&#x00;&#x02;【4】(印刷・スタンプ・手書きなどの)A, a 字.<br>
&#x1f09;&#x00;&#x02;【5】&#xE13B;数学&#xE13C;第一の既知数[量].<br>
&#x1f09;&#x00;&#x02;<b><成句></b>
</p>


旧EBStudioでは、16進コードの0x1F09 0x0002 は外字として定義されていないため、そのままEPWINGに出力していたが、EBStudio2だと「Unicodeの0x1F09(Ἁ)が出現した」と解釈してしまい、そのために文字化けが生じていた。EBStudioの本来の仕様では、制御文字を直接指定したい場合のために拡張タグを用意している。

<X4081>1F09 0002</X4081>

互換性を保つために、EBStudio win版(2.0.9)およびmacOS版(2.0.5)では、「UnicodeからEPWING外字に自動登録する」機能をオプションにした。
ランダムハウス英語辞典Toolkit」を使用する場合は、このオプションをoffで実行してほしい。

ランダムハウス英語辞典Toolkit」をWindows10で実行する

 なお、「ランダムハウス英語辞典Toolkit」では「ランダムハウス英語辞典」をインストールしてから変換する前提になっているが、インストーラがWindows10では実行できない。次の手順でインストールを行わずに変換ができる。

  1. CD-ROMの \DATAをまるごとPCの任意のディレクトリにコピー。
  2. CD-ROMのルートにあるReadme.txtを、コピーしたDATAディレクトリの中にコピー。
  3. 設定ファイルsrd2html.iniの DICPATH= と DATAPATH= に、1のコピー後のDATAディレクトリを指定する。

 

EBMac、AppStoreからrejectされる

前回EBMacをApp Store配布に切り替えると告知したが、あえなくApp Storeの審査でreject(却下)されてしまった。理由は、「EBMacというアプリケーション名称に Mac が含まれているから」。

名前が却下されてしまったのでは仕方ない。EBPocket の名称で登録してマニュアル等では "EBPocket on macOS(EBMac)"とするという方法も考えられるが、EBPocketの名称でAndroid版、iOS版、macOS版が存在することになり、問合せの時にプラットフォームを言ってもらわないと話が通じなくなる。

実は Apple notary service でAppleの認証を受ければ、これまで通り野良アプリを配付できるので、App Storeは諦めて認証を受けることにした。 

qiita.com

App Storeで配付することを想定していたので、今回からSandBox 対応になる。これまでの辞書グループ登録は引き継げないので、もう一度辞書登録を行っていただく必要がある。

とりあえずhome pageでCatalina対応の EBMac 1.44.0 を公開した。当面はこれまで通りVectorでの配布を継続するつもりである。

NotarizeされたアプリをダウンロードしてmacOS Mojave以降で実行すると、初回のみ次のような確認メッセージが表示される。そのまま開けば次回から確認なしで実効できるので、ユーザーの負担は少ない。

f:id:hishida:20191025143026p:plain

EBStudio for macOSも、2020年1月までには認証を受ける必要がある。こちらも近日中に対応する予定である。

EBMac のApp Store登録を検討中

macOS 10.15 CatalinaではEBMacが実行できないという報告を受けた。当方の環境は諸般の事情でまだ 10.14 Mojave のままなので確認できていないが、考えられる理由は次の二つ。

いずれApp Store以外からのアプリケーションのインストールが禁止される可能性もあるので、この機会にEBMac をApp Storeに登録する方向で考えている。というのは、2016年頃から、iOS Developer Program と Mac Developer Programが統合されてApple Developer Program になったので、iOSの開発者もMac のアプリケーションをApp Store に登録できるようになったからである。

このため、EBMacに次の改造が必要になる。

  • 動画の再生を、QuickTimeからiOS由来のAVFoundationに変更する。
  • Sandboxに対応する

このうちSandbox対応の方が大変である。

EPWING辞書はSandboxの外にある。NSOpenPanelで開いたパス(EBMacでは辞書ファイルのパス)はアプリの起動中はアクセス権限があるが、アプリを閉じると権限が消えてしまい、次回起動時はアクセスできなくなる。そこでsecurity-scoped bookmarkにパスを保存すると、次回起動時にアクセス権限を付与することができる。この方法で実現しようと思っている。

 

 

Android コンテキストメニューへのEBPocketの登録と検索

Android M(6.0)以降では、Google翻訳をインストールすると、ブラウザ等のアプリのコンテキストメニューに"翻訳"が現れ、選択したテキストの翻訳を行うことができる。同様に、MDict等の辞書アプリをインストールすると、コンテキストメニューに辞書アプリ名が表示され、選択したテキストで辞書引きができる。
「EBPocketでは対応しないのか」と海外のユーザからの問い合わせがあったので、調査したところ簡単に対応できそうなので実装してみた。Android M以降にEBPocketをインストールすると、次のようにコンテキストメニューにEBPocketが登録される。

f:id:hishida:20191016081031p:plain

実装方法は下記の通り。

1.AndroidManfest.xmlにaction.PROCESS_TEXTのインテントフィルターを追加する。これで他アプリのコンテキストメニューにアプリ名が表示される。

     <intent-filter>
        <action android:name="android.intent.action.PROCESS_TEXT" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>

2.ACTION_PROCESS_TEXTのハンドラを作成する

@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
。。。
	handleIntent(getIntent());
}

@Override
protected void onNewIntent(Intent intent) {
	// android:launchMode="singleTop" にした場合、
	// 2回目以降のActivityの呼び出しで呼ばれる
	handleIntent(intent);
}

private void handleIntent(Intent intent) {

	String queryAction = intent.getAction();

	if (Intent.ACTION_SEARCH.equals(queryAction)) {
		// handles a search query
		String queryString = intent.getStringExtra(SearchManager.QUERY);
		//  queryStringで検索
	}
	else if (Intent.ACTION_PROCESS_TEXT.equals(queryAction)) {
		Bundle extras = intent.getExtras();
		if (extras != null) {
			CharSequence ext = extras.getCharSequence(Intent.EXTRA_PROCESS_TEXT);
			if (ext != null) {
				String queryString = (String) ext;
				//  queryStringで検索
			}
		}
	}
}

参考になる記事:

medium.com

読書尚友 暗号化PDF対応他

読書尚友の最近の改良について。

パスワードで保護されたPDFの表示

読書尚友ではPDFの表示にAndroidPDFViewを使用している。このライブラリはパスワード付PDFにも対応しているので、サポートしてみた。

github.com

パスワード付のPDFを開くときに下記のようにパスワードの入力を求める。

f:id:hishida:20190922084453p:plain

実現方法だが、最初にpassword(null)でload()を試み、パスワード付の場合はOnErrorで定義したハンドラに飛ぶので、その中でダイアログでパスワードを入力して再度パスワードを指定してload()を行う。

private String mFilePath;
private int pageNumber;
private PDFView pdfView;


pdfView = (PDFView)findViewById(R.id.pdfView);
DoOpenPDF(null);    // パスワード無しでopenを試みる

private void DoOpenPDF(String _password) {
    File file = new File(mFilePath);
    if (file.exists()) {
        pdfView.recycle();
        pdfView.fromFile(file)
            .enableSwipe(true) //スワイプオンオフ
            .swipeHorizontal(swipeHorizontal) // T:横スクロール F:縦スクロール
            .enableDoubletap(true)  // ダブルタップでの拡大
            .defaultPage(pageNumber)
            .onPageChange(this)
            .enableAnnotationRendering(false)
            .onLoad(this)
            .onError(this)
            .scrollHandle(new DefaultScrollHandle(this))
            .password(_password)
            .pageFling(swipeHorizontal)
            .load();
    }
}

// loadが成功した後に呼ばれる
@Override
public void loadComplete(int nbPages) {
    metaData = pdfView.getDocumentMeta();
    if ( metaData != null ) {
        String title = metaData.getTitle();

	    //

    }
}

// load	が失敗した場合に呼ばれる。
@Override
public void onError(Throwable t) {
    if ( t.getMessage().equals("Password required or incorrect password.")) {

        final EditText editText = new EditText(this);

        editText.setSingleLine();   //  1行モード
        editText.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_CLASS_TEXT);
        //  パスワードとして入力
        new AlertDialog.Builder(this)
                .setTitle( getString(R.string.str_incorrect_password) )
                .setView(editText)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String value = editText.getText().toString();
                        DoOpenPDF(value);
                    }
                })
                .show();
    }
}


作品リストの絞り込み検索、高速スクロール他

  1. 作品リストに表示される件数が多い場合に目的の作品を見つけるのが困難なので、作品リストの上部に絞り込み検索の窓をもうけた。
  2. ListViewにsetFastScrollEnabled(true)を適用して右端に高速スクロールのためのつまみが表示されるようにした。ただし項目の右側のボタン(縦の…)が押しにくくなるので、右端からボタンまでの距離を多めにとって調整した。
  3. これまでは、「ダウンロードした作品にダウンロード済みのマークを表示」していたが、本棚と表示方法を統一し、「未ダウンロードの作品に雲マークを表示する」ように変更した。

f:id:hishida:20190922084503p:plain

Android 9 でのhttp通信に対応

今後GooglePlayにアプリを提出するときにtargetSdkVersion=28以上が強制されるようになるので、今回からtargetSdkVersion=28にしたところ、Android 9(Pie)で実行するときにデフォルトではhttp:が許可されず、https:でないと通信ができないようになった。

本当はドメイン毎にhttpを許可する実装が望ましいが、安直な回避方法は、manifestに次の記述を加えるとhttp通信が許可できる。

android:usesCleartextTraffic="true"

 

 

EBPocket for Android 夜間モード対応

Zenfone Max pro M2 をファームアップAndroid 9(Pie)にバージョンアップしたところ、開発者向けオプションの中にNight Modeの設定があることに気がついた。

f:id:hishida:20190903182011p:plain

「自動」に設定してみると夕暮れ時頃にNight Modeに変わる。読書尚友は既に夜間モード対応を入れていたが、EBPocketはまだだったので、この機会に夜間モード対応にしてみた。

ebstudio.hatenablog.com

夜間モードのEBPocket。いい感じですね。

f:id:hishida:20190903182028p:plain

iOS13でもダークモードがサポートされるという話なので、そろそろEBPocket iPhone版も重い腰を上げて対応しないといけないかも。

EBPocket for Android 最近の更新

最近のEBPocket for Androidの更新内容についてご紹介したい。

EPWING系辞書のブックマーク、履歴対応

これまで内部的な事情でブックマークや履歴はEPWING系辞書(電子ブックEB/EBXAやロゴヴィスタを含む)しか対応していなかったが、今回の改良で、非EPWING系辞書(StarDict、MDict、PDIC、ユーザ辞書)もブックマーク、履歴に登録できるようになった。

アダプティブアイコン対応

最近スマートフォンAsus Zenfone Max Pro M2(Android8.1)に変えたところ、EBPocketのアイコンが小さく表示されることに気がついた。どうもtargetSDKを26(Android8.0)以上にしていると、アダプティブアイコンへの対応が必須になるらしい。

アダプティブアイコンはアイコンのバックグラウンドとフォアグラウドを別々に指定し、丸や楕円やスクエアなどシステム側でトリミングして表示する仕組みである。バックグラウンドは画像でもいいし単色指定でもいい。

Android StudioのImage Assetを使うとオリジナルの512x512の図形があれば、自動的にAndroid7.1用の丸アイコンと、8.0用のアダプティブアイコンを作成してくれる。

f:id:hishida:20190616173929p:plain

辞書検索パスの指定でSDカードのアイコンを表示

SDカードに入れた辞書の設定の仕方がわからないという声をずいぶんいただくので、辞書検索パスの設定画面に内蔵ストレージのホームと外部SDのアイコンを追加した。これで指定がしやすくなったと思う。 

f:id:hishida:20190616173913p:plain