hishidaの開発blog

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

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




 

EBWin4.7 公開!~ドッキングウインドウ、単語帳~

予告していたEBWin4のドッキングウインドウ対応が実用レベルに達したので、先行公開することにした。

EB series support page

 合わせて以前から気になっていた問題点にいろいろ対応したので、過去最大のアップデートになった。

ドッキングウインドウ、タブモード

検索結果、ブックマーク、本文などのウインドウを、画面の上下左右に自由にドッキングできる。
タブモードでは辞書毎に本文ウインドウが開くので、タブで切り替えて参照したり、タイル上に配置して、辞書毎に語釈の違いを読み比べたりできる。

押しピンを外すと自動開閉モードになる。下のスクリーンショットでは、右端にドッキングした複合検索がAutoHide状態になっている。「複合検索」のタブをクリックするとパネルが開く。

f:id:hishida:20190519083645p:plain

EPWING系辞書(PDIC,StarDict,MDict,ユーザ辞書)のブックマーク対応

内部的な事情で、これまでのEBシリーズではブックマークに登録できる辞書はEPWING系だけで、PDIC、StarDict、MDict、ユーザ辞書をブックマークに登録できなかった。今回やっと全ての辞書の種類でブックマークに登録できるようになった。
EBWin4以外のプラットフォームの対応だが、ソースの共通化が進んでいるEBPocket for Android はすぐに対応できると思う。Mac版とiOS版は対応に時間がかかる見込みである。

単語帳

今回のもう一つの目玉だが、外部の単語帳を読み込んで検索できるようになった。

f:id:hishida:20190528181441p:plain

単語帳に読み込んだ語を選択すると、現在選択された辞書で検索を行う(串刺し検索も可)。
見本の単語帳として、次のテキストデータを配布ファイルに同梱している。

www.newgeneralservicelist.org


本当は単語の学習にはAnkiなどのほうが向いていると思うが、辞書を引いてみたい場合もあると思うので、実験的に導入してみた。

 

EBWin4 のドッキングウインドウ化を実験中

KWIC Finderのリニューアルで導入したドッキングウィンドウがなかなか便利なので、EBWin4にも導入してみることにした。
C#Windows Form のドッキングウィンドウのライブラリには、DockPanel Suiteを使用している。

DockPanel Suite - The .NET WinForms Docking Library

ドッキングウィンドウ化したEBWin4の画面例。

f:id:hishida:20190519083645p:plain

検索結果、ブックマーク、検索履歴、複合検索パネル、辞書本文を独自のペインとして画面上の好きなところに配置できる。
辞書本文はタブ形式で表示することもできるし、タイル形式で配置することもできる。

次の画面では、辞書本文はタブ形式表示で、複合検索パネルと検索結果を並べて表示している例。

f:id:hishida:20190519083709p:plain

手元ではほぼ動いているが、大型のアップデートなのでまだ一ヶ月くらいはテスト期間をおいてから公開したい。

こういう便利なライブラリが簡単に見つかるのがC#のいいところだ。EBMacも同様の複数辞書表示をしてほしいという要望が過去にあったが、Mac版の実装はたぶん無理だと思う。