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

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

ただいまの
回答率

90.11%

ActivityのSpinnerの値をServiceへ送れません

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 297

mssgm

score 7

前提・実現したいこと

初めて質問させていただきます。
Androidでアプリやブラウザ上に仮想ボタンのようなものを表示させ続けるアプリを作ろうと考えております。
現在、アプリのトップ画面を形成するActivity内にServiceを開始する(仮想ボタンを表示させる)ボタンとSpinnerを設定しており、Spinnerで選択された値によって仮想ボタンが表示される初期位置を決められるようにしたいと考えております。
そこで、Activity内のSpinnerで選択された値をService側へ送ればよいのではないかと考えており、intentを使ってActivityからServiceへ値を送りたいと考えております。しかし、Service側で値が参照できないのか、うまく値を送ることができません。
ActivityからServiceへ値を送るにはどうすればよいのでしょうか?よくわかっていない部分も多く、コードも見づらいとは思いますがどなたかご助力いただければ幸いです。

Compilation failed; see the compiler error output for details.

該当のソースコード

【MainActivity.java】

import android.annotation.TargetApi;
        import android.content.Intent;
        import android.net.Uri;
        import android.os.Build;
        import android.provider.Settings;
        import android.support.v7.app.AppCompatActivity;
        import android.os.Bundle;
        import android.util.Log;
        import android.view.View;
        import android.widget.AdapterView;
        import android.widget.ArrayAdapter;
        import android.widget.Button;
        import android.widget.Spinner;

public class MainActivity extends AppCompatActivity {

    public static int OVERLAY_PERMISSION_REQ_CODE = 1000;

    public String spinnerItems[] = {"①","②","③","④"};

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

        Button backHomeButton = findViewById(R.id.Button1);
        backHomeButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                // ホーム画面に戻るインテントを起動
                Intent homeIntent = new Intent(Intent.ACTION_MAIN);
                homeIntent.addCategory(Intent.CATEGORY_HOME);
                homeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                MainActivity.this.startActivity(homeIntent);
            }
        });

        Spinner spinner = findViewById(R.id.spinner);

        // ArrayAdapter
        ArrayAdapter<String> adapter
                = new ArrayAdapter<>(this,
                android.R.layout.simple_spinner_item, spinnerItems);

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        // Spinnerにadapterをセット
        spinner.setAdapter(adapter);

        // リスナーを登録
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            // アイテムが選択された時
            @Override
            public void onItemSelected(AdapterView<?> parent,
                                       View view, int position, long id) {
                Spinner spinner = (Spinner)parent;
                final String item = (String)spinner.getSelectedItem();

                // Serviceを開始するためのボタン
                final Button bt = findViewById(R.id.Button2);
                bt.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        if(item.equals("①")) {
                            Intent intent = new Intent(getApplication(), TestService.class);
                            // intentにデータを入れる
                            intent.putExtra("①", item);
                            // Serviceの開始
                            // API26以上
                            startForegroundService(intent);
                            bt.setEnabled(false);
                        }else if(item.equals("②")) {
                            Intent intent = new Intent(getApplication(), TestService.class);
                            intent.putExtra("②", item);
                            startForegroundService(intent);
                            bt.setEnabled(false);
                        }else if(item.equals("③")) {
                            Intent intent = new Intent(getApplication(), TestService.class);
                            intent.putExtra("③", item);
                            startForegroundService(intent);
                            bt.setEnabled(false);
                        }else{
                            Intent intent = new Intent(getApplication(), TestService.class);
                            intent.putExtra("④", item);
                            startForegroundService(intent);
                            bt.setEnabled(false);
                        }

                    }
                });
            }

            // アイテムが選択されなかった
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        // API 23 以上であればPermission checkを行う
        //if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        checkPermission();
        //}


    }

    @TargetApi(Build.VERSION_CODES.M)
    public void checkPermission() {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                    Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
        }
    }

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (!Settings.canDrawOverlays(this)) {
                Log.d("debug","SYSTEM_ALERT_WINDOW permission not granted...");
                // SYSTEM_ALERT_WINDOW permission not granted...
                // nothing to do !
            }
        }
    }
}
【TestService.java】

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TableLayout;

public class TestService extends Service {

    //画面に全面表示させるビュー
    private View view;
    private WindowManager windowManager;
    private int dpScale;
    private ImageButton button1, button2, button3, button4, button5, button6;
    private TableLayout tableLayout;

    @Override
    public void onCreate() {
        super.onCreate();

        // dipを取得
        dpScale = (int)getResources().getDisplayMetrics().density;

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) { // startServiceでサービスが開始要求を受けた時のコールバック。
        // startForegroundService() -----

        Context context = getApplicationContext();
        String channelId = "default";
        String title = context.getString(R.string.app_name);

       ~(略)~
        Intent intent = getIntent();
        String item = intent.getStringExtra("①,②,③,④");
        params.gravity = Gravity.TOP | Gravity.END;
        if(item = intent.getStringExtra("①")) {
            // 左上(①)に配置
            params.x = 200 * dpScale; // 200dp
            params.y = 80 * dpScale; // 80dp
        }else if(item = intent.getStringExtra("②")) {
            // 右上(②)に配置
            params.x = 20 * dpScale; // 20dp
            params.y = 80 * dpScale; // 80dp
        }else if(item = intent.getStringExtra("③")) {
            // 左下(③)に配置
            params.x = 200 * dpScale; // 200dp
            params.y = 300 * dpScale; //
        }else {
                // 右下(④)に配置
                params.x = 20 * dpScale; // 20dp
                params.y = 300 * dpScale; // 300dp
        }
~(略)~

試したこと

Intent intent = getIntent();
   ~(略)~       
                // 右下(④)に配置
                params.x = 20 * dpScale; // 20dp
                params.y = 300 * dpScale; // 300dp
        }


の部分にエラーが出ております。if文(あるいはそれ以外の条件文)を使うこと自体がおかしいのか、ServiceではgetIntentを用いること自体ができないのか、様々なサイトを調べましたが、解決方法が見つかりませんでした。

補足情報(FW/ツールのバージョンなど)

言語:Java
開発環境:Android Studio3.1.3

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • jimbe

    2019/02/14 11:53

    > Intent intent = new Intent(getApplication(), TestService.class);
    > iintent.putExtra("①", item);
    > startForegroundService(intent);
    として起動したサービスで, 入れたはずの値が
    > Intent intent = getIntent();
    > String item = intent.getStringExtra("①,②,③,④");
    で取れないということでよろしいでしょうか?
    また, 結果 String item にはどのような値が入る予定なのでしょうか.
    そして, 実際にはどのような値が入ってきていますか?
    極力具体的なデータのご提示をお願い致します.

    エラーが出たとのことですが, そのエラーはどのような内容でしたでしょうか.
    また, 試されたことによって発生したように思えますが, ご質問には直接関係するのでしょうか?

    キャンセル

  • jimbe

    2019/02/14 12:01

    失礼, エラーというのはもしやコンパイルエラーでしょうか.

    > if(item = intent.getStringExtra("①")) {
    > }else if(item = intent.getStringExtra("②")) {
    > }else if(item = intent.getStringExtra("③")) {
    まず, 比較は '=' では無く '==' です.
    次に, String の同値比較は '==' では無く equals メソッドです.

    キャンセル

  • mssgm

    2019/02/14 16:31

    ご回答ありがとうございます。
    エラーの内容はコンパイルエラーです。
    そして、仰る通りActivity側で入れた(と思うんですけど)値が
    >Intent intent = getIntent();
    >String item = intent.getStringExtra("①,②,③,④");
    で取れないということです。
    結果としては、String itemにはspinnerで選択した値が入ってくるようにしたいと考えております(spinnerで①を選んだら仮想ボタンを表示するボタンを押したときに①の入った値をService側のintentに送りたい。②、③、④も同様)。

    キャンセル

回答 1

checkベストアンサー

0

単純に見まして, Intent での putExtra/getStringExtra の使い方を勘違いされておられるようです.

両メソッドの定義は

Intent putExtra(String name, String value);

String getStringExtra(String name);


で, name をキーとして putExtra で設定した value が getStringExtra の戻り値として返されるというものです.
ですから, 対応する putExtra と getStringExtra で指定する name は 同じ文字列 で無ければなりません.
putExrta で "①" や "②" をキーとして指定するからと言って, "①,②" と 「この中の何れか」のような指定はありません.

この件の場合, "①" "②" 等はどちらかと言いますと value です.
ですので, 例えば name を "item" としますと, MainActivity では

Intent intent = new Intent(getApplication(), TestService.class);
// intentにデータを入れる
intent.putExtra("item", item); //itemには"①"等が入っている


とし, TestService では

String item = intent.getStringExtra("item"); //item に"①"等が入る


のように name が対応するように記述してください.
これによりまして, また例えばですが, ①②等以外に何かメッセージを送る必要が出来た場合,

intent.putExtra("message", "文字列");
String text = intent.getStringExtra("message"); //text に "文字列" が入る


として name を変えていけば, データが混ざること無く取り込めます.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/02/18 15:28

    ご回答ありがとうございます。なるほど、指定の仕方がおかしかったのですね。ご回答いただいたことをもとに再度やってみたいと思います。

    キャンセル

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

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる