Androidで着信コール用のブロードキャストレシーバーを開発しています。着信コールを取得すると、ネイティブの着信コール画面でポップアップを膨らませたいと思います。
そのコードを完成させました。しかし今の問題は、 Android 4.1(Jelly bean)APIレベル17 で、電話が鳴ったときにPHONE_STATE
はOFF HOOK
、アクティビティを呼び出している場合は呼び出されますが、その下のコードは実行されません。私はコードをリストしています:
package com.example.popwindowonincomingcallscreen;
import Java.util.concurrent.Executors;
import Java.util.concurrent.ScheduledExecutorService;
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.telephony.TelephonyManager;
import Android.util.Log;
public class IncomingBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d("IncomingBroadcastReceiver: onReceive: ", "flag1");
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
Log.d("IncomingBroadcastReceiver: onReceive: ", state);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)
|| state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) {
Log.d("Ringing", "Phone is ringing");
Intent i = new Intent(context, IncomingCallActivity.class);
i.putExtras(intent);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
Wait.oneSec();
context.startActivity(i);
}
}
}
私が呼んでいる活動:
import Android.app.Activity;
import Android.os.Bundle;
import Android.telephony.TelephonyManager;
import Android.util.Log;
import Android.view.View.MeasureSpec;
import Android.view.Window;
import Android.view.WindowManager;
import Android.widget.TextView;
public class IncomingCallActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
try {
Log.d("IncomingCallActivity: onCreate: ", "flag2");
*/ After this line, the code is not executed in Android 4.1 (Jelly bean) only/*
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
Log.d("IncomingCallActivity: onCreate: ", "flagy");
setContentView(R.layout.main);
Log.d("IncomingCallActivity: onCreate: ", "flagz");
String number = getIntent().getStringExtra(
TelephonyManager.EXTRA_INCOMING_NUMBER);
TextView text = (TextView) findViewById(R.id.text);
text.setText("Incoming call from " + number);
}
catch (Exception e) {
Log.d("Exception", e.toString());
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
後
try {
Log.d("IncomingCallActivity: onCreate: ", "flag2");
}
コードはAndroid 4.1(Jelly bean)では実行されていませんが、他のバージョンでは機能しています。
私はできる限りの方法を試しました。このコードは、ネイティブコール画面に半透明のアクティビティを表示しており、電話を拾うなどのバックグラウンドコントロールをブロックしません。しかし、私はそれを本当の発信者のようにしたい。実際の発信者が着信画面にウィンドウを表示する方法のスナップショットを添付しました。
Androidアプリでこの機能を実現するにはどうすればよいですか?
これが真の発信者の仕組みです:
私の現在の出力:
報奨金を受け取った後も、探しているものが正確に得られませんが、すべてに戻ります。私はそれに取り組んでいます。とにかく、このコードはほとんどのAndroid携帯電話で動作します。誰かがそのソリューションを使用してキャッチしようとしている場合は、誰もが利益を得ることができるようにここに書いてください。
ToastはAndroidのネイティブコンポーネントであるため、ブロードキャストレシーバーのonReceiveメソッドにToastを実装しようとしましたが、Android 4.1(Jelly bean)では表示されません。
私のアイデアは、放送受信機のonReceiveメソッドにToastを実装し、その後、ニーズに応じてデザインを変更し、表示期間を調整することでした。しかし、もう1つの問題は、findViewByIdがブロードキャストレシーバーで機能しないため、トーストをカスタマイズするためにプログラムでLinearLayoutを作成する必要があると思います。
システムブロードキャストレシーバーとレシーバーの両方が画面の上部にGUIを表示しようとしているため、カスタムGUIが常にデフォルトGUIの上にあるかどうかはわかりません。どちらが最初に呼び出されるのかはわかりませんが、画面の上部にGUIを作成するための注意が必要な作業の1つは、電話が鳴っているときに1〜2秒後にハンドラーを使用してアクティビティを呼び出すことです。
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Intent intent = new Intent(context, AcceptReject.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}, 2000);
それがあなたのお役に立てば幸いです。
super.onCreate
メソッドの前にコードを試してください。スーパーを呼び出した後、コードはスキップされると思います。いつか、この種のトリックがうまくいきました。
Android 4.2(Jelly bean) エミュレータでテストしたところ、truecallerのように着信画面全体をブロックすることで完璧に動作します。
public void onReceive(Context context, Intent intent) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.height = LayoutParams.MATCH_PARENT;
params.width = LayoutParams.MATCH_PARENT;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.TOP;
LinearLayout ly = new LinearLayout(context);
ly.setBackgroundColor(Color.RED);
ly.setOrientation(LinearLayout.VERTICAL);
wm.addView(ly, params);
}
マニフェストで:
<receiver Android:name="" Android:enabled="true" >
<intent-filter Android:priority="-1">
<action Android:name="Android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
私もそれに取り組んでいます(ここであなたを理解するのは間違っているかもしれません)。達成したいのは、そのアクティビティをAndroid 4.2(Jelly bean)で表示することです。アクティビティを表示するのに遅延をかけました。別のクラスでPhoneStateListenerを使用しました。表示できます。発信者画面の新しいアクティビティ。ここに私の完全なコードがあります。
public class MyBroadcastReceiver extends BroadcastReceiver {
static CustomPhoneStateListener phoneStateListener;
Context context;
Intent intent;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
this.intent = intent;
// TODO Auto-generated method stub
TelephonyManager telephonyManager = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
phoneStateListener = new CustomPhoneStateListener(context);
telephonyManager.listen(phoneStateListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
}
public class CustomPhoneStateListener extends PhoneStateListener {
// private static final String TAG = "PhoneStateChanged";
Context context; // Context to make Toast if required
private AudioManager amanager;
Intent i1;
public CustomPhoneStateListener(Context context) {
super();
this.context = context;
i1 = new Intent(context, YourActivity.class);
i1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i1.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
Toast.makeText(context, "Phone state Idle", Toast.LENGTH_LONG)
.show();
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Toast.makeText(context, "Phone state Off hook", Toast.LENGTH_LONG)
.show();
break;
case TelephonyManager.CALL_STATE_RINGING:
try {
Thread.sleep(3000);
context.startActivity(i1);
} catch (Exception e) {
e.getLocalizedMessage();
}
default:
break;
}
}
yourActivityは作成したまま残ります...注:ここにあるこのコードでもいくつかの問題に直面しています。
(これらの問題についてはヘルプが受け入れられました。ありがとう。誰かを助けるかもしれません)
[〜#〜] update [〜#〜]
こちらIS LINK OF SMALL DEMO) これを達成する方法。
着信画面に追加のボタンを追加して、同様のことを試みています。
私がPhoneStateListenerからコードを呼び出していますが、Sam Adamsが投稿した答えは私にとっては有効です。それとは別に、彼のコードとの唯一の本当の違いは、レイアウトを拡張していることです:
overlay = (RelativeLayout) inflater.inflate(R.layout.overlay, null);
wm.addView(overlay, params);
HTC One Sと同様にエミュレーターでも動作しています(Android 4.1.1)を実行しています)。
覚えておく必要があるのは、追加するオーバーレイビューへの参照を保持し、電話がアイドル状態に戻ったとき(リスナーがTelephonyManager.CALL_STATE_IDLEを取得したとき)に再度削除する(windowmanagerインスタンスでremoveView()を呼び出す)ことです。オーバーレイは画面に残ります。
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if(overlay!=null)
{
wm.removeView(overlay);
overlay = null;
}
記述された結果を達成するために活動を開始すべきではないと思います。レイアウトパラメータにLayoutParams.TYPE_SYSTEM_OVERLAY
が設定された別のビューが必要です。
このビューは、画面上の任意の場所に配置することも、画面全体をカバーすることもできます。
コードの数行は次のとおりです。
_av = new ActivatorView(this);
_avLayoutParams = new WindowManager.LayoutParams(0, 0, 0, 0,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
PixelFormat.OPAQUE);
_avLayoutParams.screenBrightness = _fScreenBrightness = 20f;
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(_av, _avLayoutParams);
https://bitbucket.org/gyrussolutions/yaab/src/f01cc8aff690cae1b1107287cb17835b8a3c1643/src/biz/gyrus/yaab/LightMonitorService.java?at=default#cl-338 -完全なソースコードであると考えてくださいサンプル。
また、ピンロックのあるデバイスでオーバーレイが表示されないという同様の問題に直面していました。私たちのために働いた解決策は以下の通りです:
mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
mParams = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT,
LayoutParams.TYPE_SYSTEM_ERROR,
LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
そうだった LayoutParams.TYPE_SYSTEM_ERROR
違いを生みました。
私の方法:
サービスを使用してオーバーレイを作成する
ps:wmParams.type = WindowManager.LayoutParams.TYPE_PHONE;
これを試して
AlertDialog.Builder builder = new AlertDialog.Builder(context.getApplicationContext());
LayoutInflater inflater = LayoutInflater.from(context);
View dialogView = inflater.inflate(R.layout.caller_dialog, null);
ImageView button = dialogView.findViewById(R.id.close_btn);
builder.setView(dialogView);
final AlertDialog alert = builder.create();
alert.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
alert.getWindow().setType(WindowManager.LayoutParams.TYPE_PHONE);
alert.setCanceledOnTouchOutside(true);
alert.show();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
Window window = alert.getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.setGravity(Gravity.TOP);
lp.copyFrom(window.getAttributes());
//This makes the dialog take up the full width
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
window.setAttributes(lp);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//close the service and remove the from from the window
alert.dismiss();
}
});
シンプルなブロードキャストレシーバーを使用して、このコードをブロードキャストレシーバーに配置します。
public void onReceive(final Context context, final Intent intent) {
Log.v(LOG_TAG, "Receieved notification about network status");
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT |
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.format = PixelFormat.TRANSLUCENT;
params.gravity = Gravity.TOP;
LinearLayout ly = new LinearLayout(context);
ly.setBackgroundColor(Color.RED);
ly.setOrientation(LinearLayout.VERTICAL);
wm.addView(ly, params);
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Intent i = new Intent(context, CallingIncoming.class);
i.putExtras(intent);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*| Intent.FLAG_ACTIVITY_CLEAR_TASK*/);
context.startActivity(i);
}
}, 450);//It will help you to delay your screen and after it your screen will be top of default app screen