質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

449閲覧

Serviceから指定した領域に矩形を表示したい

sunmo

総合スコア10

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2018/07/31 06:26

編集2018/08/01 16:51

前提・実現したいこと

以下のようなAndroidアプリを作りたいと思っています。
1)Serviceを使ってオーバレイのボタンを配置し、そのボタンを押すことでスクショを取ります。
2)スクショの中に指定した画像を見つけます。
3)見つけた領域に矩形などをオーバレイ表示する。

発生している問題・エラーメッセージ

1)は、色々なサイトを参考に、WindowManager、MediaProjectionManagerなどを使用して
何とか作成することができたと思います。
2)はビットマップからRGBを抽出し、座標、大きさは取得できました。
※正しくは、抽出するロジックはまだこれからなので、調べたい領域を抜き出すところまでです。
3)において、調べたい領域が正しく抜き出されているのかを確認する意味で、
その矩形をオーバレイ上に追加したいのですが、この方法がわかりません。

Java初心者で見様見真似で作っているので、理解できていないところが多く
見当違いなことを書いているかもしれませんが、解決方法についてご教授お願いいたします。

該当のソースコード

Java

1 @Override 2 public int onStartCommand(Intent intent, int flags, int startId){ 3 super.onStartCommand(intent, flags, startId); 4 5 LayoutInflater layoutInflater = LayoutInflater.from(this); 6 7 WindowManager.LayoutParams params = null; 8 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { 9 params = new WindowManager.LayoutParams( 10 WindowManager.LayoutParams.WRAP_CONTENT, 11 WindowManager.LayoutParams.WRAP_CONTENT, 12 WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, 13 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 14 WindowManager.LayoutParams.FLAG_FULLSCREEN | 15 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 16 PixelFormat.TRANSLUCENT); 17 }else 18 { 19 params = new WindowManager.LayoutParams( 20 WindowManager.LayoutParams.WRAP_CONTENT, 21 WindowManager.LayoutParams.WRAP_CONTENT, 22 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 23 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | 24 WindowManager.LayoutParams.FLAG_FULLSCREEN | 25 WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, 26 PixelFormat.TRANSLUCENT); 27 } 28 29 wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); 30 31 view = layoutInflater.inflate(R.layout.overlay, null); 32 33 params.gravity= Gravity.TOP | Gravity.CENTER; 34 35 View.OnClickListener buttonClickListener = new View.OnClickListener() { 36 @Override 37 public void onClick(View view) { 38 switch(view.getId()) { 39 case R.id.start: 40 41 // 画面の縦横サイズとdpを取得 42 DisplayMetrics displayMetrics = new DisplayMetrics(); 43 wm.getDefaultDisplay().getMetrics(displayMetrics); 44 screenDensity = displayMetrics.densityDpi; 45 displayWidth = displayMetrics.widthPixels; 46 displayHeight = displayMetrics.heightPixels; 47 48 imageReader = ImageReader.newInstance( 49 displayWidth, displayHeight, PixelFormat.RGBA_8888, 2); 50 51 virtualDisplay = MainActivity.mProjection.createVirtualDisplay("ScreenCapture", 52 displayWidth, displayHeight, screenDensity, 53 DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 54 imageReader.getSurface(), null, null); 55 56 //スクリーンショット取得 57 Bitmap btMap = getScreenshot(); 58 //Bitmapの解析 59 BitmapAnalyze test = new BitmapAnalyze(); 60 Rect rect1; 61 //抽出された領域の取得 62 rect1 = test.AreaKettei(btMap); 63 //■■■■■■■■■■■■■■■■■■■■■ここに記述?? 64 //2018.08.02追記 ===> 65 AnalyzeResultView AnalyzeResult = new AnalyzeResultView(getApplicationContext()); 66 AnalyzeResult.setAnalyzeResult(rect1); 67 //<===2018.08.02追記 68 break; 69 case R.id.stop: 70 stopSelf(); 71 Intent intent2 = new Intent(getApplication(), MainActivity.class); 72 startActivity(intent2); 73 break; 74 } 75 } 76 }; 77 view.findViewById(R.id.start).setOnClickListener(buttonClickListener); 78 view.findViewById(R.id.stop).setOnClickListener(buttonClickListener); 79 80 wm.addView(view, params); 81 82 return START_STICKY; 83 } 84

試したこと

「ここに記述??」と書いたところにに何かを記載すればいいのかなと思うのですが、
実現方法がわかりません。

⇒ 2018/08/02追記
ご記載いただいたカスタムViewを作成し、上記ソースにも追記して呼び出してみたのですが、
onDrawが呼ばれない現象になりました。
こちらを解消する方法はありますでしょうか?

Java

1public class AnalyzeResultView extends View { 2 3 private Rect rect = null; 4 private Paint mPaint = new Paint(); 5 6 public AnalyzeResultView(Context context) { 7 super(context); 8 setWillNotDraw(false); 9 } 10 11 // 結果をセットし描画を更新するためのメソッド 12 public void setAnalyzeResult(Rect rect) { 13 this.rect = rect; 14 postInvalidate(); 15 16 } 17 18 @Override 19 public void onDraw(Canvas canvas) { 20 super.onDraw(canvas); 21 22 mPaint.setAntiAlias(true); 23 mPaint.setStrokeWidth(1); 24 mPaint.setStyle(Paint.Style.STROKE); 25 26 mPaint.setColor(Color.YELLOW); 27 // 矩形の描画処理... 28 canvas.drawRect(rect,mPaint); 29 } 30 31} 32

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

カスタムViewクラスを作成して、onDrawの中で矩形の描画処理を実装してみてはどうでしょう?

java

1// 実装イメージ 2public class AnalyzeResultView extends View { 3 private Rect rect = null; 4 5 ... 6 7 // 結果をセットし描画を更新するためのメソッド 8 public void setAnalyzeResult(Rect rect) { 9 this.rect = rect; 10 postInvalidate(); 11 } 12 13 @Override 14 public void onDraw(Canvas canvas) { 15 super.onDraw(canvas); 16 // 矩形の描画処理... 17 } 18}

投稿2018/08/01 13:18

kakajika

総合スコア3131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sunmo

2018/08/01 17:01

ご回答ありがとうございます。早速試してみたのですが、onDrawが呼ばれない現象になりました。 ネットを調べてみて、「setWillNotDraw(false);」を追加してみたのですが、こちらもダメでした。 こちらの原因は、何かわかりますでしょうか? ※追加したソースは質問内容を更新させていただきました。 MainActivityから開始ボタンクリックでstartServiceを呼び出して、サービスを起動し、 ボタンを表示させています。 そのボタンをクリックすることで、スクリーンショットをとって画像解析としたいのですが、 使い方が悪いのでしょうか?
kakajika

2018/08/01 17:22 編集

説明を省いてしまいましたが、カスタムViewはレイアウト(ご質問のコードの場合はR.layout.overlayに当たるもの)の中に追加してください。レイアウトに追加しなければViewは表示されませんからonDrawが呼ばれることもありません(setWillNotDrawは関係ないです)。コードで追加してもいいですし、xml内に追加してfindViewByIdで取得して利用するのでもOKです。
sunmo

2018/08/02 17:17

初歩的なことだと思うので恐縮なのですが、カスタムViewをレイアウトに追加するとは、R.layout.overlayに下記の記述を追加することと思ったのですが、認識あっていますでしょうか? <overlay.xml抜粋> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  ・・・・  <LinearLayout   ・・・・ボタンなど </LinearLayout> <LinearLayout   ・・・・  <view class="com.example.sumsu.overlaytest2.AnalyzeResultView" id="@+id/view" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> これにより、最初にサービスを起動したときにonDrawが呼ばれたのですが、オーバレイ表示されているボタンを押しても、onDrawが呼ばれることはありませんでした。 ソース側にも何か記載が必要なのでしょうか?
kakajika

2018/08/02 22:46

はい、レイアウトへの追加についてはその認識であっています。 あとは、プログラム側でレイアウト内のAnalyzeResultViewを取得して、setAnalyzeResultメソッドで結果をセットすれば描画が更新されるはずです。 ※setAnalyzeResultの中にあるpostInvalidate()というのがViewの描画更新を促すためのメソッドです。 // レイアウトの中にあるAnalyzeResultViewを取得し、結果をセットする AnalyzeResultView resultView = (AnalyzeResultView) view.findViewById(R.id.view); resultView.setAnalyzeResult(rect1);
sunmo

2018/08/03 16:20

何度もありがとうございます。ご記載のソースを追加したところ、上記の「resultView」がNullになり、例外になってしまいました。findViewById(R.id.view)の「view」がカスタムViewのidと思っているのですが、試しに、XMLに追加したカスタムViewのidを変更しましたが、「R.id.」と入力しても候補に現れませんでした。ちなみにソースを追加した箇所は、「rect1 = test.AreaKettei(btMap);」の下です。
sunmo

2018/08/03 17:25

一つ訂正です。「「R.id.」と入力しても候補に現れませんでした」は見間違いでした。候補にありました。
kakajika

2018/08/04 15:01

ソースを追加する場所は問題ないと思います。 ご質問のコードをよく読み返してみたら原因がわかりました。R.layout.overlayをinflateした結果をviewという変数に入れていたのでview.findViewById(...)で取得できるはずと思ったのですが、OnClickListenerのonClickの引数もviewという名前になっているのでこちらの中を探しに行ってしまっているようです。2つが被らないように変更してください。
sunmo

2018/08/05 15:53

表示できました!ご指摘の通りviewの変数がかぶっていたため、イベントで取得したほうのviewを使用していたようです。クリックイベントのViewの変数名をview1など違うものに変えることで表示できました。 まだ別の問題も出てきましたが、今回の質問内容は解決できましたので、もう少し色々試してみたいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問