黑科技小demo,实现定时自动打电话,挂断电话

好久没写博客了,实在是太忙了,又鉴于鄙人天生爱睡觉。幸运的是,上周终于把自己的第一个Apk写好了,,接下来,就写个小系列来记录一下吧。不过,在此之前,先把这篇黑科技写起来(研究了小段时间,确实好玩)。

原理思路:1、利用alarm机制来定时
              2、利用广播,启动新的Activity拨打电话
              3、利用反射机制,取得手机状态,接通后一定时间挂断

先上图片吧黑科技小demo,实现定时自动打电话,挂断电话_第1张图片

接下来上详细的代码块:

一、点设置之后会有一个timepickDialog弹出,用来设置AlarmClock的启动时间

	btnSettting.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				c.setTimeInMillis(System.currentTimeMillis());
				new TimePickerDialog(MainActivity.this,
						new OnTimeSetListener() {

							@Override
							public void onTimeSet(TimePicker view,
									int hourOfDay, int minute) {
								clockHour = hourOfDay;
								clockMinute = minute;
								phoneTime.setText(clockHour + " : "
										+ clockMinute);
							}
						}, c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE),
						true).show();
			}
		});
分析:还是很好理解的,clockHour和clockMinute分别用来记录拨打的小时、分钟


二、通过PendingIntent结合Alarm来定时启动广播

btnStart.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
				Calendar calendar = Calendar.getInstance();
				intent = new Intent(MainActivity.this, PhoneBroadcast.class);
				intent.putExtra("phoneNumber", phoneNumber.getText().toString());
				pIntent = PendingIntent.getBroadcast(MainActivity.this, 0,
						intent, 0);
				calendar.setTimeInMillis(System.currentTimeMillis());
				calendar.set(Calendar.HOUR_OF_DAY, clockHour);
				calendar.set(Calendar.MINUTE, clockMinute);
				calendar.set(Calendar.SECOND, 0);
				calendar.set(Calendar.MILLISECOND, 0);
				alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
						calendar.getTimeInMillis(), DURATION_TIME, pIntent);
				Toast.makeText(MainActivity.this,
						"已启动,时间是" + clockHour + " : " + clockMinute,
						Toast.LENGTH_SHORT).show();
			}
		});
分析:这边也比较好理解,主要是用到AlarmManager类来管理闹钟,取得实例后,setRepeating方法来设置闹钟。四个参数分别为,闹钟模式(4种,可百度),闹钟启动时间,重复间隔,PendingIntent。

自定义的BroadCast

public class PhoneBroadcast extends BroadcastReceiver{

	@Override
	public void onReceive(Context context, Intent intent) {
		Intent intent2=new Intent(context, PhoneActivity.class);
		intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		intent2.putExtra("phoneNumber",intent.getStringExtra("phoneNumber") );
		context.startActivity(intent2);
	}

}
用来启动打电话的Activity

第三步:难点

这边有点复杂的,老实说我并没有完全弄懂

ITelephony这个接口不能直接用的。需要先在src下黑科技小demo,实现定时自动打电话,挂断电话_第2张图片

新建包com.android.internal.telephony,在其中新建一个File,后缀为aidl(它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口),内容如下

package com.android.internal.telephony;
interface ITelephony{
boolean endCall();
void answerRingingCall();
}
这之后会在gen目标下生成对应java文件(你无法修改,但是可以用ITelephoney接口了)

回到打电话的Activity,先上代码。

package com.dota.example.autophoneapp;

import java.lang.reflect.Method;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.WindowManager;

import com.android.internal.telephony.ITelephony;

public class PhoneActivity extends Activity {
	private ITelephony itelephony;
	private TelephonyManager manager;
	public Handler mHandler;
	private Thread mThread;
	private static final int END_CALL_REQUEST = 1;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_phone);
		getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
						| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
		Intent intent = getIntent();
		String phoneNumber = intent.getStringExtra("phoneNumber");
		Intent intentPhone = new Intent(Intent.ACTION_CALL);
		intentPhone.setData(Uri.parse("tel:" + phoneNumber));
		startActivity(intentPhone);
		phoner();
		mHandler=new Handler(){
			@Override
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				switch (msg.what) {
				case END_CALL_REQUEST:
					try {
						itelephony.endCall();
						finish();
					} catch (RemoteException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					break;

				default:
					break;
				}
			}
		};
		mThread=new NewThread();
		manager.listen(new PhoneStateListener() {
			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				super.onCallStateChanged(state, incomingNumber);
				try {
					switch (state) {
					case TelephonyManager.CALL_STATE_OFFHOOK:
						mThread.start();
						break;

					default:
						break;
					}
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}, PhoneStateListener.LISTEN_CALL_STATE);
	}

	public void phoner() {
		manager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		Class class1 = TelephonyManager.class;
		Method getITelephonyMethod = null;
		try {
			getITelephonyMethod = class1.getDeclaredMethod("getITelephony",
					(Class[]) null);
			getITelephonyMethod.setAccessible(true);
			itelephony = (ITelephony) getITelephonyMethod.invoke(manager,
					(Object[]) null);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	class NewThread extends Thread implements Runnable {
		@Override
		public void run() {
			super.run();
			try {
				Thread.sleep(1000*20);
				Message message = new Message();
				message.what = END_CALL_REQUEST;
				mHandler.sendMessage(message);
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
}
来,慢慢分析。先从pnoner()方法入手。这里用到反射的方法,得到TelephonyManager类中的getITelephony方法,将其设置为可操作。
设置电话的监听器
manager.listen(new PhoneStateListener() {
			@Override
			public void onCallStateChanged(int state, String incomingNumber) {
				super.onCallStateChanged(state, incomingNumber);
				try {
					switch (state) {
					case TelephonyManager.CALL_STATE_OFFHOOK:
						mThread.start();
						break;

					default:
						break;
					}
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}, PhoneStateListener.LISTEN_CALL_STATE);
三种状态:RINGING(振铃)、OFFHOOK(摘机=接通)、IDLE(空闲)

这边用到Hander  Message(异步线程处理的原理),接受到状态后,启动线程,sleep20秒,执行

itelephony.endCall();
即:挂断
还有两块简单说一下:这是用来锁屏时,点亮屏幕并在锁状态下显示的方法(英语很清晰明了的)

getWindow().addFlags(
				WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
						| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
这段是用来打电话的:打电话是ACTION_CALL,设置拨打的号码为Uri.parse("tel:10086");
String phoneNumber = intent.getStringExtra("phoneNumber");
		Intent intentPhone = new Intent(Intent.ACTION_CALL);
		intentPhone.setData(Uri.parse("tel:" + phoneNumber));
		startActivity(intentPhone);

还有一些不重要的就不写了,代码里可以看到,还是很有意思的(最终我被朋友拉黑了)

源代码的百度云链接:http://pan.baidu.com/s/1i3kWH85






你可能感兴趣的:(黑科技小demo,实现定时自动打电话,挂断电话)