本当の発信者に似たアプリを実装しようとしています。ブロードキャストレシーバーを使用して電話が鳴り、MyCustomDialogアクティビティを開くと、電話番号を取得できます。
これは、通話が開始または終了したという通話状態を取得するための受信者クラスです。これでは、CallReceiver.Javaで使用しているいくつかのメソッドを作成します
PhonecallReceiver.Java
import Android.content.BroadcastReceiver;
import Android.content.Context;
import Android.content.Intent;
import Android.telephony.TelephonyManager;
import Java.util.Date;
public abstract class PhonecallReceiver extends BroadcastReceiver
{
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;
@Override
public void onReceive(Context context, Intent intent)
{
try
{
if (intent.getAction().equals("Android.intent.action.NEW_OUTGOING_CALL"))
{
savedNumber = intent.getExtras().getString("Android.intent.extra.PHONE_NUMBER");
}
else
{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE))
{
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))
{
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
state = TelephonyManager.CALL_STATE_RINGING;
}
onCallStateChanged(context, state, number);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start){}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
public void onCallStateChanged(Context context, int state, String number)
{
if(lastState == state)
{
//No change, debounce extras
return;
}
switch (state)
{
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallStarted(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if (isIncoming)
{
onIncomingCallEnded(context,savedNumber,callStartTime,new Date());
}
case TelephonyManager.CALL_STATE_IDLE:
if(isIncoming)
{
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
}
lastState = state;
}
}
CallReceiver.Java
import Android.app.Activity;
import Android.app.Dialog;
import Android.app.Notification;
import Android.content.ComponentName;
import Android.content.Context;
import Android.content.Intent;
import Android.graphics.drawable.ColorDrawable;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.Window;
import Android.widget.Button;
import Android.widget.Toast;
import Android.os.Handler;
import Java.util.Date;
import dootam.dspl.com.lawyercasecall.R;
public class CallReceiver extends PhonecallReceiver
{
Context context;
@Override
protected void onIncomingCallStarted(final Context ctx, String number, Date start)
{
Toast.makeText(ctx,"Kushal Incoming Call"+ number,Toast.LENGTH_LONG).show();
context = ctx;
final Intent intent = new Intent(context, MyCustomDialog.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.putExtra("phone_no",number);
new Handler().postDelayed(new Runnable()
{
@Override
public void run()
{
context.startActivity(intent);
}
},2000);
// MyCus/*tomDialog dialog = new MyCustomDialog(context);
// dialog.*/show();
}
@Override
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
{
Toast.makeText(ctx,"Bye Bye"+ number,Toast.LENGTH_LONG).show();
}
}
MyCustomDialog.Java
import Android.app.Activity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.view.Window;
import Android.widget.Button;
import Android.widget.TextView;
import dootam.dspl.com.lawyercasecall.R;
public class MyCustomDialog extends Activity
{
TextView tv_client;
String phone_no;
Button dialog_ok;
@Override
protected void onCreate(Bundle savedInstanceState)
{
try
{
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setFinishOnTouchOutside(false);
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog);
initializeContent();
/*WindowManager.LayoutParams params = getWindow().getAttributes();
params.x = -100;
params.height = 70;
params.width = 1000;
params.y = -50;
this.getWindow().setAttributes(params);*/
phone_no = getIntent().getExtras().getString("phone_no");
tv_client.setText(""+phone_no +" is calling you");
dialog_ok.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
MyCustomDialog.this.finish();
// this.setFinishOnTouchOutside(false);
System.exit(0);
}
});
}
catch (Exception e)
{
Log.d("Exception", e.toString());
e.printStackTrace();
}
}
private void initializeContent()
{
tv_client = (TextView) findViewById(R.id.tv_client);
dialog_ok = (Button) findViewById(R.id.dialog_ok);
}
}
私のAndroidManifest.xml
<application
Android:allowBackup="true"
Android:icon="@mipmap/ic_launcher"
Android:label="@string/app_name"
Android:theme="@style/AppTheme" >
<activity
Android:name=".AddCasesActivity"
Android:label="@string/app_name" >
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity Android:name=".receiver.MyCustomDialog"
Android:theme="@Android:style/Theme.Dialog"
Android:noHistory="true"
/>
<receiver Android:name=".receiver.CallReceiver" >
<intent-filter>
<action Android:name="Android.intent.action.PHONE_STATE" />
</intent-filter>
<intent-filter>
<action Android:name="Android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
<uses-permission Android:name="Android.permission.READ_PHONE_STATE" />
<uses-permission Android:name="Android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission Android:name="Android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions"/>
<uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW" />
これらすべてを実装することで、目的の出力が得られます
このアクティビティダイアログをtruecallerアプリのポップアップのようにドラッグ可能にする方法を教えてください。
この画像に似たダイアログを探しています、
OnTouchListenerを介して可能です。これを試してください https://github.com/andreilisun/Swipe-To-Dismiss-Dialog ダイアログはドラッグ可能です。次のように、SwipeDimissDialogを変更してダイアログの却下を削除しました。クラス-
public class SwipeDismissDialog extends FrameLayout {
private final Params params;
private View dialog;
protected SwipeDismissDialog(@NonNull Context context, Params params) {
super(context);
this.params = params;
init();
}
private void init() {
setOnClickListener(overlayClickListener);
setBackgroundColor(params.overlayColor);
dialog = params.view;
if (dialog == null) {
dialog = LayoutInflater.from(getContext()).inflate(params.layoutRes, this, false);
}
LayoutParams layoutParams = (LayoutParams) dialog.getLayoutParams();
if (layoutParams == null) {
layoutParams = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER);
} else {
layoutParams.gravity = Gravity.CENTER;
}
dialog.setOnTouchListener(touchListener);
addView(dialog, layoutParams);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN
&& event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
cancel();
return true;
}
return false;
}
public SwipeDismissDialog show() {
WindowManager windowManager = (WindowManager)
getContext().getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION;
layoutParams.format = PixelFormat.TRANSLUCENT;
windowManager.addView(this, layoutParams);
return this;
}
public void cancel() {
if (params.cancelListener != null) {
params.cancelListener.onCancel(dialog);
}
if (params.dismissOnCancel) {
dismiss();
}
}
public void dismiss() {
dialog.setOnTouchListener(null);
removeView(dialog);
WindowManager windowManager = (WindowManager)
getContext().getSystemService(Context.WINDOW_SERVICE);
windowManager.removeViewImmediate(this);
}
private void dismiss(SwipeDismissDirection direction) {
if (params.swipeDismissListener != null) {
params.swipeDismissListener.onSwipeDismiss(this, direction);
}
dismiss();
}
private final OnTouchListener touchListener = new OnTouchListener() {
private float initCenterX;
private float lastEventY;
private float lastEventX;
private float initY;
private float initX;
public boolean onTouch(View view, MotionEvent motionEvent) {
/*Fling detected*/
int action = motionEvent.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
initX = view.getX();
initY = view.getY();
lastEventX = motionEvent.getRawX();
lastEventY = motionEvent.getRawY();
initCenterX = initX + view.getWidth() / 2;
break;
}
case MotionEvent.ACTION_MOVE: {
float eventX = motionEvent.getRawX();
float eventY = motionEvent.getRawY();
float eventDx = eventX - lastEventX;
float eventDy = eventY - lastEventY;
float centerX = view.getX() + eventDx + view.getWidth() / 2;
float centerDx = centerX - initCenterX;
view.setX(view.getX() + eventDx);
view.setY(view.getY() + eventDy);
//view.invalidate();
lastEventX = eventX;
lastEventY = eventY;
break;
}
}
return true;
}
};
private final OnClickListener overlayClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
cancel();
}
};
public static class Builder {
private final Params params;
private final Context context;
public Builder(Context context) {
this.context = context;
this.params = new Params();
}
public Builder setView(@NonNull View view) {
params.view = view;
params.layoutRes = 0;
return this;
}
public Builder setLayoutResId(@LayoutRes int layoutResId) {
params.layoutRes = layoutResId;
params.view = null;
return this;
}
public SwipeDismissDialog build() {
if (params.view == null && params.layoutRes == 0) {
throw new IllegalStateException("view should be set with setView(View view) " +
"or with setLayoutResId(int layoutResId)");
}
return new SwipeDismissDialog(context, params);
}
}
}