同事做的一个来电小骗子的APP,设计多长时后,虚拟一个来电界面,用户可以接听等操作,做一个小笔记,有时候对于用户来说是会有用的。
几个主要的界面:
主界面 来电界面 联系人选择界面 背景音乐选择界面
核心代码:
FakeCallActivity.java
import java.util.Calendar; import java.util.TimeZone; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.Menu; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; import android.widget.ToggleButton; public class FakeCallActivity extends Activity implements View.OnClickListener { private static final String TAG = "FakeCallActivity"; private static final boolean DEBUG = true; private static final int PICK_CONTACT_REQUEST_CODE = 101; private static final int START_SET_UP_DATE_TIME_REQUEST_CODE = 102; //hongyu hexiaoming add incall activity background music 20140306 start private static final int START_SET_UP_BACKGROUND_MUSIC_REQUEST_CODE = 103; //hongyu hexiaoming add incall activity background music 20140306 end private static final long TEN_SECOND = 10000; private static final long ONE_MINUTE = 60 * 1000; private static final long FIVE_MINUTE = 5 * 60 * 1000; private static final int SELECT_TEN_CESOND = 0; private static final int SELECT_ONE_MINUTE = 1; private static final int SELECT_FIVE_MINUTE = 2; private static final int SELECT_CUSTOMIZE_TIME = 3; //hongyu hexiaoming add incall activity background music 20140306 start private static final int BACKGROUND_MUSIC_DEFAULT = 4; private static final int BACKGROUND_MUSIC_CUSTOM = 5; //hongyu hexiaoming add incall activity background music 20140306 end private static final int HANDLER_DELAY_ONE_SECONDS = 1; private static final int DELAY_ONE_SECONDS_TIME = 1000; private static final int AM_TIME = 0; private static final int PM_TIME = 1; private static final String PROFILE_KEY = "com.hy.fakecall_preferences"; private static final String SHOW_CALL_NAME = "show_call_name"; private static final String SHOW_CALL_NUMBER = "show_call_number"; private static final String SELECT_CONTACT_NAME = "select_contact_name"; private static final String SELECT_CONTACT_NUMBER = "select_contact_number"; private static final String SETUP_CALL_TIME_MILLS = "setup_call_time_mills"; private static final String EXTRA_TIME_MILLIS = "com.hy.fakecall.EXTRA_TIME_MILLS"; private static final String EXIT_AFTER_DONE_CHECK_BOOL = "exit_after_done_check_bool"; private SharedPreferences mInCallScreenSharePred; private SharedPreferences.Editor mInCallScreenSharedEditor; private EditText mEditNameText; private EditText mEditNumberText; private ToggleButton mTenSecondButton; private ToggleButton mOneMinuteButton; private ToggleButton mFiveMinuteButton; private ToggleButton mCustomizeButton; //hongyu hexiaoming add incall activity background music 20140306 start private ToggleButton mBackgroundMusiDefault; private ToggleButton mBackgroundMusiCustom; //hongyu hexiaoming add incall activity background music 20140306 end private Button mCallMeButton; private ImageView mPickContactsIv; private CheckBox mExitAfterDoneCheckBox; private long mCallingTime; private int mWhichSelectTime; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_fake_call); // SharedPreferences Editor mInCallScreenSharePred = getSharedPreferences(PROFILE_KEY, Context.MODE_PRIVATE); mInCallScreenSharedEditor = mInCallScreenSharePred.edit(); mEditNameText = (EditText) findViewById(R.id.edit_name); mEditNumberText = (EditText) findViewById(R.id.edit_number); mPickContactsIv = (ImageView) findViewById(R.id.pick_contact); mPickContactsIv.setOnClickListener(FakeCallActivity.this); /** 10s , 1minute, 5minute, custom button **/ mTenSecondButton = (ToggleButton) findViewById(R.id.in_10_second); mOneMinuteButton = (ToggleButton) findViewById(R.id.in_1_minute); mFiveMinuteButton = (ToggleButton) findViewById(R.id.in_5_minute); mCustomizeButton = (ToggleButton) findViewById(R.id.in_custom); //hongyu hexiaoming add incall activity background music 20140306 start mBackgroundMusiDefault = (ToggleButton) findViewById(R.id.background_music_default); mBackgroundMusiCustom = (ToggleButton) findViewById(R.id.background_music_custom); //hongyu hexiaoming add incall activity background music 20140306 end // give the button setOnClickListener mTenSecondButton.setOnClickListener(FakeCallActivity.this); mOneMinuteButton.setOnClickListener(FakeCallActivity.this); mFiveMinuteButton.setOnClickListener(FakeCallActivity.this); mCustomizeButton.setOnClickListener(FakeCallActivity.this); //hongyu hexiaoming add incall activity background music 20140306 start mBackgroundMusiDefault.setOnClickListener(FakeCallActivity.this); mBackgroundMusiCustom.setOnClickListener(FakeCallActivity.this); mInCallScreenSharedEditor.putBoolean(SetupBackgroundMusicActivity.IS_CUSTOM_BACKGROUND_MUSIC, false); mInCallScreenSharedEditor.commit(); mBackgroundMusiDefault.setChecked(true); mBackgroundMusiCustom.setChecked(false); //hongyu hexiaoming add incall activity background music 20140306 end // CallMeButton mCallMeButton = (Button) findViewById(R.id.call_me); mCallMeButton.setOnClickListener(FakeCallActivity.this); mExitAfterDoneCheckBox = (CheckBox) findViewById(R.id.exit_after_done); mExitAfterDoneCheckBox.setOnCheckedChangeListener(new onCheckChangedListener()); mWhichSelectTime = SELECT_TEN_CESOND; updateButtonStatus(SELECT_TEN_CESOND); if (DEBUG) { Log.v(TAG, "onCreate() mWhichSelectTime : " + mWhichSelectTime); } boolean isFinishMe = mInCallScreenSharePred.getBoolean(EXIT_AFTER_DONE_CHECK_BOOL, getResources().getBoolean(R.bool.config_finish_activity_default)); mExitAfterDoneCheckBox.setChecked(isFinishMe); } @Override protected void onResume() { super.onResume(); String editName = mInCallScreenSharePred.getString(SHOW_CALL_NAME, getResources().getString(R.string.stranger_name)); mEditNameText.setText(editName); String editNumber = mInCallScreenSharePred.getString(SHOW_CALL_NUMBER, getResources().getString(R.string.stranger_number)); mEditNumberText.setText(editNumber); //hongyu hexiaoming add incall activity background music 20140306 start boolean isCustomBgMusic = mInCallScreenSharePred.getBoolean(SetupBackgroundMusicActivity.IS_CUSTOM_BACKGROUND_MUSIC, false); if(isCustomBgMusic){ mBackgroundMusiDefault.setChecked(false); mBackgroundMusiCustom.setChecked(true); }else{ mBackgroundMusiDefault.setChecked(true); mBackgroundMusiCustom.setChecked(false); } //hongyu hexiaoming add incall activity background music 20140306 start } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. //getMenuInflater().inflate(R.menu.fake_call, menu); return true; } @Override public void onClick(View v) { if (DEBUG) { Log.v(TAG, "onClick() v : " + v + ", v.getId() : " + v.getId()); } switch (v.getId()) { case R.id.pick_contact: pickContacts(); break; case R.id.in_10_second: updateButtonStatus(SELECT_TEN_CESOND); break; case R.id.in_1_minute: updateButtonStatus(SELECT_ONE_MINUTE); break; case R.id.in_5_minute: updateButtonStatus(SELECT_FIVE_MINUTE); break; case R.id.in_custom: startSetupDataTimeActivity(); mHandler.sendEmptyMessageDelayed(HANDLER_DELAY_ONE_SECONDS, DELAY_ONE_SECONDS_TIME); if (mWhichSelectTime == SELECT_CUSTOMIZE_TIME) { setCustomizeButton(); } break; //hongyu hexiaoming add incall activity background music 20140306 start case R.id.background_music_default: updateButtonStatus(BACKGROUND_MUSIC_DEFAULT); break; case R.id.background_music_custom: updateButtonStatus(BACKGROUND_MUSIC_CUSTOM); startSetupBackgroundMusicActivity(); break; //hongyu hexiaoming add incall activity background music 20140306 end case R.id.call_me: callMeButton(); break; default: Log.v(TAG, "onClick() is default click ... ... "); break; } } private class onCheckChangedListener implements CompoundButton.OnCheckedChangeListener { @Override public void onCheckedChanged(CompoundButton button, boolean bool) { if (DEBUG) { Log.v(TAG, "onCheckedChanged() button : " + button + ", bool : " + bool); } mInCallScreenSharedEditor.putBoolean(EXIT_AFTER_DONE_CHECK_BOOL, bool); mInCallScreenSharedEditor.commit(); } } private void pickContacts() { Intent pickContactsIntent = new Intent(); pickContactsIntent.setClass(FakeCallActivity.this, PickContacts.class); startActivityForResult(pickContactsIntent, PICK_CONTACT_REQUEST_CODE); } private void startSetupDataTimeActivity() { Intent startDataTimeIntent = new Intent(); startDataTimeIntent.setClass(FakeCallActivity.this, SetupDateTimeActivity.class); startActivityForResult(startDataTimeIntent, START_SET_UP_DATE_TIME_REQUEST_CODE); } //hongyu hexiaoming add incall activity background music 20140306 start private void startSetupBackgroundMusicActivity() { Intent startBackgroundMusicIntent = new Intent(); startBackgroundMusicIntent.setClass(FakeCallActivity.this, SetupBackgroundMusicActivity.class); startActivity(startBackgroundMusicIntent); //startActivityForResult(startBackgroundMusicIntent, START_SET_UP_BACKGROUND_MUSIC_REQUEST_CODE); } //hongyu hexiaoming add incall activity background music 20140306 end private void callMeButton() { String callName = mEditNameText.getText().toString(); String callNumber = mEditNumberText.getText().toString(); if (DEBUG) { Log.v(TAG, "callMeButton() callName : " + callName + ", callNumber : " + callNumber); } mInCallScreenSharedEditor.putString(SHOW_CALL_NAME, callName); mInCallScreenSharedEditor.putString(SHOW_CALL_NUMBER, callNumber); mInCallScreenSharedEditor.commit(); Intent intent = new Intent(FakeCallActivity.this, CallMeAlarm.class); PendingIntent sender = PendingIntent.getBroadcast( FakeCallActivity.this, 1, intent, 0); AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); // set the Calling time ring setCallRingTime(); am.set(AlarmManager.RTC_WAKEUP, mCallingTime, sender); boolean isFinishMe = mInCallScreenSharePred.getBoolean(EXIT_AFTER_DONE_CHECK_BOOL, getResources().getBoolean(R.bool.config_finish_activity_default)); if (isFinishMe) { FakeCallActivity.this.finish(); } Toast.makeText(FakeCallActivity.this, R.string.alarm_call_me_success, Toast.LENGTH_LONG).show(); } private void updateButtonStatus(int which) { switch (which) { case SELECT_TEN_CESOND: mWhichSelectTime = SELECT_TEN_CESOND; mTenSecondButton.setChecked(true); mOneMinuteButton.setChecked(false); mFiveMinuteButton.setChecked(false); mCustomizeButton.setChecked(false); break; case SELECT_ONE_MINUTE: mWhichSelectTime = SELECT_ONE_MINUTE; mTenSecondButton.setChecked(false); mOneMinuteButton.setChecked(true); mFiveMinuteButton.setChecked(false); mCustomizeButton.setChecked(false); break; case SELECT_FIVE_MINUTE: mWhichSelectTime = SELECT_FIVE_MINUTE; mTenSecondButton.setChecked(false); mOneMinuteButton.setChecked(false); mFiveMinuteButton.setChecked(true); mCustomizeButton.setChecked(false); break; case SELECT_CUSTOMIZE_TIME: mTenSecondButton.setChecked(false); mOneMinuteButton.setChecked(false); mFiveMinuteButton.setChecked(false); mCustomizeButton.setChecked(true); break; //hongyu hexiaoming add incall activity background music 20140306 start case BACKGROUND_MUSIC_DEFAULT: mBackgroundMusiDefault.setChecked(true); mBackgroundMusiCustom.setChecked(false); break; case BACKGROUND_MUSIC_CUSTOM: mBackgroundMusiDefault.setChecked(false); mBackgroundMusiCustom.setChecked(true); break; //hongyu hexiaoming add incall activity background music 20140306 end default: Log.v(TAG, "updateButtonStatus() is default click ... ... "); break; } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != RESULT_OK) { finish(); return; } if (requestCode == PICK_CONTACT_REQUEST_CODE) { if (data == null) return; String contactName = data.getStringExtra(SELECT_CONTACT_NAME); mEditNameText.setText(contactName); String contactNumber = data.getStringExtra(SELECT_CONTACT_NUMBER); mEditNumberText.setText(contactNumber); mInCallScreenSharedEditor.putString(SHOW_CALL_NAME, contactName); mInCallScreenSharedEditor.putString(SHOW_CALL_NUMBER, contactNumber); mInCallScreenSharedEditor.commit(); if (DEBUG) { Log.v(TAG, "onActivityResult() : contactName : " + contactName + ", contactNumber : " + contactNumber); } } else if (requestCode == START_SET_UP_DATE_TIME_REQUEST_CODE) { if (data != null) { long miiliseconds = data.getLongExtra(EXTRA_TIME_MILLIS, -1); if (miiliseconds != -1) { mWhichSelectTime = SELECT_CUSTOMIZE_TIME; updateButtonStatus(mWhichSelectTime); mInCallScreenSharedEditor.putLong(SETUP_CALL_TIME_MILLS, miiliseconds); mInCallScreenSharedEditor.commit(); setCustomizeButton(); } else { updateButtonStatus(mWhichSelectTime); if (mWhichSelectTime == SELECT_CUSTOMIZE_TIME) { setCustomizeButton(); } } } else { updateButtonStatus(mWhichSelectTime); } } //super.onActivityResult(requestCode, resultCode, data); } private void setCustomizeButton() { long timemills = mInCallScreenSharePred.getLong(SETUP_CALL_TIME_MILLS, System.currentTimeMillis()); Calendar calendar = Calendar.getInstance(TimeZone.getDefault()); calendar.setTimeInMillis(timemills); int year = calendar.get(Calendar.YEAR); // the first month is begin 0 int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); int hour = calendar.get(Calendar.HOUR); int minute = calendar.get(Calendar.MINUTE); int am_pm = calendar.get(Calendar.AM_PM); if (DEBUG) { Log.v(TAG, "setCustomizeButton() : year : " + year + ", month : " + month + ", day : " + day + "\n" + "====, hour : " + hour + ", minute : " + minute + ", am_pm : " + am_pm); } if (am_pm == AM_TIME) { mCustomizeButton.setText(month + getResources().getString(R.string.month_show) + day + getResources().getString(R.string.day_show) + getResources().getString(R.string.am_show) + " " + hour + ":" + minute); } else if (am_pm == PM_TIME) { mCustomizeButton.setText(month + getResources().getString(R.string.month_show) + day + getResources().getString(R.string.day_show) + getResources().getString(R.string.pm_show) + " " + hour + ":" + minute); } } private void setCallRingTime() { Log.v(TAG, "setCallRingTime() mWhichSelectTime : " + mWhichSelectTime); switch (mWhichSelectTime) { case SELECT_TEN_CESOND: mCallingTime = System.currentTimeMillis() + TEN_SECOND; break; case SELECT_ONE_MINUTE: mCallingTime = System.currentTimeMillis() + ONE_MINUTE; break; case SELECT_FIVE_MINUTE: mCallingTime = System.currentTimeMillis() + FIVE_MINUTE; break; case SELECT_CUSTOMIZE_TIME: mCallingTime = mInCallScreenSharePred.getLong(SETUP_CALL_TIME_MILLS, System.currentTimeMillis()); break; default: Log.v(TAG, "updateButtonStatus() is default click ... ... "); break; } } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case HANDLER_DELAY_ONE_SECONDS: if (DEBUG) Log.v(TAG, "handleMessage HANDLER_DELAY_ONE_SECONDS ..."); updateButtonStatus(SELECT_CUSTOMIZE_TIME); break; default: Log.v(TAG, "mHandler: unexpected message: " + msg); break; } } }; @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (DEBUG) Log.v(TAG, "onConfigurationChanged ..." + newConfig.orientation); } }
CallMeAlarm.xml
import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class CallMeAlarm extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Intent callViewIntent = new Intent(context, InCallScreen.class); callViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); context.startActivity(callViewIntent); } }
incall_screen.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="80dp" android:layout_above="@+id/show_incoming_image" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" > <TextView android:id="@+id/show_call_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="left" android:text="@string/who_call_me" android:textColor="@color/white" android:textSize="16.0dip" android:layout_weight="1" android:textStyle="bold" /> <TextView android:id="@+id/show_call_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/who_call_me" android:textColor="@color/white" android:gravity="right" android:textSize="16.0dip" android:layout_weight="1" android:textStyle="bold" /> </LinearLayout> <TextView android:id="@+id/show_city_name" android:layout_width="fill_parent" android:layout_height="20dip" android:layout_marginTop="5dip" android:gravity="right" android:text="@string/show_city_name" android:textColor="@color/white" android:textSize="16.0dip" android:textStyle="bold" /> <TextView android:id="@+id/show_call_info" android:layout_width="fill_parent" android:layout_height="25dip" android:layout_marginTop="5dip" android:paddingBottom="2dip" android:background="@drawable/vt_incall_btn_bkg_foc" android:gravity="left" android:text="@string/show_incall_come_info" android:textColor="@color/white" android:textSize="16.0dip" android:textStyle="bold" /> </LinearLayout> <ImageView android:id="@id/show_incoming_image" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:contentDescription="@string/unkown_picture" android:src="@drawable/picture_unknown" android:layout_above="@+id/incomingCallWidget" /> <com.android.internal.widget.multiwaveview.GlowPadView android:id="@id/incomingCallWidget" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_gravity="center|bottom" android:layout_marginBottom="-110dip" android:background="@android:color/black" android:gravity="top" prvandroid:directionDescriptions="@array/incoming_call_widget_3way_direction_descriptions" prvandroid:feedbackCount="1" prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius" prvandroid:handleDrawable="@drawable/ic_in_call_touch_handle" prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius" prvandroid:outerRadius="@*android:dimen/glowpadview_target_placement_radius" prvandroid:outerRingDrawable="@*android:drawable/ic_lockscreen_outerring" prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot" prvandroid:snapMargin="@*android:dimen/glowpadview_snap_margin" prvandroid:targetDescriptions="@array/incoming_call_widget_3way_target_descriptions" prvandroid:targetDrawables="@array/incoming_call_widget_3way_targets" prvandroid:vibrationDuration="20" /> </RelativeLayout>
InCallScreen.java
import com.android.internal.widget.multiwaveview.GlowPadView; import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.AudioManager.OnAudioFocusChangeListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.os.Vibrator; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.ViewPropertyAnimator; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; public class InCallScreen extends Activity implements OnTriggerListener{ private static final boolean DEBUG = true; private static final String TAG = "InCallScreen"; private static final String PROFILE_KEY = "com.hy.fakecall_preferences"; private static final String SHOW_CALL_NAME = "show_call_name"; private static final String SHOW_CALL_NUMBER = "show_call_number"; private static final boolean ENABLE_PING_AUTO_REPEAT = true; private static final int INCOMING_CALL_WIDGET_PING = 101; private static final long PING_AUTO_REPEAT_DELAY_MSEC = 1200; private static final int ANIMATION_DURATION = 250; // Incoming call widget targets private static final int ANSWER_CALL_ID = 0; // drag right private static final int SEND_SMS_ID = 1; // drag up private static final int DECLINE_CALL_ID = 2; // drag left private GlowPadView mIncomingCallWidget; // UI used for an incoming call private TextView mShowCallNameTv; private TextView mShowCallNumberTv; private SharedPreferences mInCallScreenSharePred; private SharedPreferences.Editor mInCallScreenSharedEditor; private MediaPlayer mMediaPlayer; private AudioManager mAudioManager; private Vibrator mVibrator; /// M: Use member variable to show toast to avoid show the toast on screen for a long time if user click many time. private Toast mToast; private String mShowNameStr; private String mShowNumberStr; private boolean mIncomingCallWidgetIsFadingOut; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final Window window = getWindow(); final WindowManager.LayoutParams lp = window.getAttributes(); // set this flag so this activity will let the Home Key Fail // set this flag so this activity will stay in front of the keyguard and // set the Screen on lp.flags |= WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; window.setAttributes(lp); mAudioManager = (AudioManager) InCallScreen.this.getSystemService(Context.AUDIO_SERVICE); setContentView(R.layout.incall_screen); // SharedPreferences mInCallScreenSharePred = getSharedPreferences(PROFILE_KEY, Context.MODE_PRIVATE); mInCallScreenSharedEditor = mInCallScreenSharePred.edit(); // "Drag-to-answer" widget for incoming calls. mIncomingCallWidget = (GlowPadView) findViewById(R.id.incomingCallWidget); mIncomingCallWidget.setOnTriggerListener(this); showIncomingCallWidget(); mShowCallNameTv = (TextView) findViewById(R.id.show_call_name); mShowCallNumberTv = (TextView) findViewById(R.id.show_call_number); mShowNameStr = mInCallScreenSharePred.getString(SHOW_CALL_NAME, getResources().getString(R.string.stranger_name)); mShowNumberStr = mInCallScreenSharePred.getString(SHOW_CALL_NUMBER, getResources().getString(R.string.stranger_number)); mShowCallNameTv.setText(mShowNameStr); mShowCallNumberTv.setText(mShowNumberStr); int ringerMode = mAudioManager.getRingerMode(); if (DEBUG) { Log.v(TAG, "onCreate() : ringerMode : " + ringerMode); } if (ringerMode == AudioManager.RINGER_MODE_NORMAL) { playRingtone(); } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); final int MO_CALL_VIBRATE_TIME = 300; // msec //mVibrator.vibrate(MO_CALL_VIBRATE_TIME); mVibrator.vibrate(new long[]{1000, 1000, 1000, 1000}, 0); } } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { super.onDestroy(); if (mVibrator != null) { mVibrator.cancel(); } mAudioManager.abandonAudioFocus(mAudioFocusChangeListener); } /** * Handles "Answer" and "Reject" actions for an incoming call. * We get this callback from the incoming call widget * when the user triggers an action. */ @Override public void onTrigger(View view, int whichHandle) { if (DEBUG) Log.v(TAG, "onTrigger(whichHandle = " + whichHandle + ")..."); switch (whichHandle) { case ANSWER_CALL_ID: if (DEBUG) Log.v(TAG, "ANSWER_CALL_ID: answer!"); stopRingtone(); if (mVibrator != null) { mVibrator.cancel(); } Intent mCallIntent = new Intent(); mCallIntent.setClass(InCallScreen.this, CallingScreen.class); startActivity(mCallIntent); finishActivity(); break; case SEND_SMS_ID: stopRingtone(); if (mVibrator != null) { mVibrator.cancel(); } finishActivity(); break; case DECLINE_CALL_ID: stopRingtone(); if (mVibrator != null) { mVibrator.cancel(); } finishActivity(); break; default: Log.v(TAG, "onDialTrigger: unexpected whichHandle value: " + whichHandle); break; } } public void onFinishFinalAnimation() { // Not used } /** * Handles state changes of the incoming-call widget. * * In previous releases (where we used a SlidingTab widget) we would * display an onscreen hint depending on which "handle" the user was * dragging. But we now use a GlowPadView widget, which has only * one handle, so for now we don't display a hint at all (see the TODO * comment below.) */ @Override public void onGrabbedStateChange(View v, int grabbedState) { // Look up the hint based on which handle is currently grabbed. // (Note we don't simply pass grabbedState thru to the InCallScreen, // since *this* class is the only place that knows that the left // handle means "Answer" and the right handle means "Decline".) switch (grabbedState) { case GlowPadView.OnTriggerListener.NO_HANDLE: case GlowPadView.OnTriggerListener.CENTER_HANDLE: break; default: Log.e(TAG, "onGrabbedStateChange: unexpected grabbedState: " + grabbedState); break; } } @Override public void onGrabbed(View v, int handle) { } @Override public void onReleased(View v, int handle) { } /** * Shows the incoming call widget and cancels any animation that may be fading it out. */ private void showIncomingCallWidget() { ViewPropertyAnimator animator = mIncomingCallWidget.animate(); if (animator != null) { animator.cancel(); } mIncomingCallWidget.setAlpha(1.0f); final int targetResourceId = R.array.incoming_call_widget_3way_targets; mIncomingCallWidget.setTargetResources(targetResourceId); mIncomingCallWidget.setHandleDrawableImage(R.drawable.ic_in_call_touch_handle); mHandler.removeMessages(INCOMING_CALL_WIDGET_PING); mHandler.sendEmptyMessageDelayed( INCOMING_CALL_WIDGET_PING, // Visual polish: add a small delay here, to make the // GlowPadView widget visible for a brief moment // *before* starting the ping animation. // This value doesn't need to be very precise. 250 /* msec */); } /** * Apply an animation to hide the incoming call widget. */ private void hideIncomingCallWidget() { if (DEBUG) Log.v(TAG, "hideIncomingCallWidget()..."); ViewPropertyAnimator animator = mIncomingCallWidget.animate(); animator.cancel(); animator.setDuration(ANIMATION_DURATION); animator.setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (DEBUG) Log.v(TAG, "IncomingCallWidget's hiding animation started"); // Hide the incoming call screen with a transition // mIncomingCallWidgetIsFadingOut should be set as true here // because hiding animation is canceled before start, onAnimationEnd() and onAnimationCancel() will be // be called mIncomingCallWidgetIsFadingOut = true; } @Override public void onAnimationEnd(Animator animation) { if (DEBUG) Log.v(TAG, "IncomingCallWidget's hiding animation ended"); mIncomingCallWidget.setAlpha(1); mIncomingCallWidget.setVisibility(View.GONE); /// M: For ALPS00557477 @{ // hide mIncomingMenuButton just after hide mIncomingCallWidget, or // mIncomingMenuButton will move to parent layout. // // MTK add /// @} mIncomingCallWidget.animate().setListener(null); } @Override public void onAnimationCancel(Animator animation) { if (DEBUG) Log.v(TAG, "IncomingCallWidget's hiding animation Canceled"); mIncomingCallWidget.animate().setListener(null); // Note: the code which reset this animation should be responsible for // alpha and visibility. } }); animator.alpha(0f); } private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case INCOMING_CALL_WIDGET_PING: if (DEBUG) Log.v(TAG, "INCOMING_CALL_WIDGET_PING..."); triggerPing(); break; default: Log.v(TAG, "mHandler: unexpected message: " + msg); break; } } }; /** * Runs a single "ping" animation of the GlowPadView widget, * or do nothing if the GlowPadView widget is no longer visible. * * Also, if ENABLE_PING_AUTO_REPEAT is true, schedule the next ping as * well (but again, only if the GlowPadView widget is still visible.) */ public void triggerPing() { if (DEBUG) Log.v(TAG, "triggerPing: mIncomingCallWidget = " + mIncomingCallWidget); if (mIncomingCallWidget == null) { // This shouldn't happen; the GlowPadView widget should // always be present in our layout file. Log.w(TAG, "- triggerPing: null mIncomingCallWidget!"); return; } if (DEBUG) Log.v(TAG, "- triggerPing: mIncomingCallWidget visibility = " + mIncomingCallWidget.getVisibility()); if (mIncomingCallWidget.getVisibility() != View.VISIBLE) { if (DEBUG) Log.v(TAG, "- triggerPing: mIncomingCallWidget no longer visible; ignoring..."); return; } // Ok, run a ping (and schedule the next one too, if desired...) mIncomingCallWidget.ping(); if (ENABLE_PING_AUTO_REPEAT) { // Schedule the next ping. (ENABLE_PING_AUTO_REPEAT mode // allows the ping animation to repeat much faster than in // the ENABLE_PING_ON_RING_EVENTS case, since telephony RING // events come fairly slowly (about 3 seconds apart.)) // No need to check here if the call is still ringing, by // the way, since we hide mIncomingCallWidget as soon as the // ringing stops, or if the user answers. (And at that // point, any future triggerPing() call will be a no-op.) // TODO: Rather than having a separate timer here, maybe try // having these pings synchronized with the vibrator (see // VibratorThread in Ringer.java; we'd just need to get // events routed from there to here, probably via the // PhoneGlobals instance.) (But watch out: make sure pings // still work even if the Vibrate setting is turned off!) mHandler.sendEmptyMessageDelayed(INCOMING_CALL_WIDGET_PING, PING_AUTO_REPEAT_DELAY_MSEC); } } private void playRingtone() { // M: When request AudioFocus failed, we should not play music and need toast user maybe the /// phone call is ongoing. @{ if (AudioManager.AUDIOFOCUS_REQUEST_FAILED == mAudioManager.requestAudioFocus( mAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)) { showToast(getString(R.string.audiofocus_request_failed_message)); Log.w(TAG, "<< play: phone call is ongoing, can not play music!"); return; } /// @} Uri localUri = Uri.parse("content://settings/system/ringtone"); this.mMediaPlayer = new MediaPlayer(); if (localUri == null) return; try { this.mMediaPlayer.setDataSource(this, localUri); if (((AudioManager) getSystemService(Context.AUDIO_SERVICE)).getStreamVolume(2) > 0) { this.mMediaPlayer.setAudioStreamType(2); this.mMediaPlayer.setLooping(true); this.mMediaPlayer.prepare(); this.mMediaPlayer.start(); } } catch (Exception localException) { return; } } private void stopRingtone() { if (this.mMediaPlayer == null) return; this.mMediaPlayer.stop(); this.mMediaPlayer.release(); this.mMediaPlayer = null; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { stopRingtone(); InCallScreen.this.finish(); return true; } return true; } /** * use to interact with other voice related app */ private final OnAudioFocusChangeListener mAudioFocusChangeListener = new OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_LOSS: stopRingtone(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: stopRingtone(); break; case AudioManager.AUDIOFOCUS_GAIN: playRingtone(); break; default: Log.d(TAG, "AudioFocus: Audio focus change, but not need handle"); break; } } }; /** * M: Show the given text to screen. * * @param toastText Need show text. */ private void showToast(CharSequence toastText) { if (mToast == null) { mToast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_LONG); } mToast.setText(toastText); mToast.show(); } private void finishActivity() { InCallScreen.this.finish(); } }
SetupDateTimeActivity.java
import java.util.Calendar; import java.util.TimeZone; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.Button; import android.widget.DatePicker; import android.widget.TimePicker; import android.widget.TimePicker.OnTimeChangedListener; public class SetupDateTimeActivity extends Activity implements View.OnClickListener, DatePicker.OnDateChangedListener, OnTimeChangedListener{ private static final boolean DEBUG = true; private static final String TAG = "SetupDateTimeActivity"; private static final String EXTRA_TIME_MILLIS = "com.hy.fakecall.EXTRA_TIME_MILLS"; private Calendar mCalendar = Calendar.getInstance(TimeZone.getDefault()); private Button mOkView; private Button mCancelView; private DatePicker mDatePick; private TimePicker mTimePick; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.setup_date_time); // init the layout UI initViewRes(); initStatus(); } private void initViewRes() { mDatePick = (DatePicker) findViewById(R.id.setup_date); mTimePick = (TimePicker) findViewById(R.id.setup_time); mTimePick.setOnTimeChangedListener(this); mOkView = (Button) findViewById(R.id.left_ok); mOkView.setOnClickListener(SetupDateTimeActivity.this); mCancelView = (Button) findViewById(R.id.right_cancel); mCancelView.setOnClickListener(SetupDateTimeActivity.this); } private void initStatus() { mCalendar.setTimeInMillis(System.currentTimeMillis()); this.mDatePick.init(this.mCalendar.get(Calendar.YEAR), this.mCalendar.get(Calendar.MONTH), this.mCalendar.get(Calendar.DAY_OF_MONTH), SetupDateTimeActivity.this); Log.v(TAG, "initStatus() mCalendar.get(Calendar.HOUR) : " + mCalendar.get(Calendar.HOUR) + "\n" + " ====== , mCalendar.get(Calendar.MINUTE) : " + mCalendar.get(Calendar.MINUTE)); this.mTimePick.setCurrentHour(Integer.valueOf(this.mCalendar.get(Calendar.HOUR_OF_DAY))); this.mTimePick.setCurrentMinute(Integer.valueOf(this.mCalendar.get(Calendar.MINUTE))); } @Override public void onClick(View v) { if (v == mOkView) { getCurrentFocus().clearFocus(); int year = mDatePick.getYear(); // the first month is begin 0 int month = mDatePick.getMonth(); int day = mDatePick.getDayOfMonth(); int hour = mTimePick.getCurrentHour(); int minute = mTimePick.getCurrentMinute(); this.mCalendar.set(Calendar.YEAR, this.mDatePick.getYear()); this.mCalendar.set(Calendar.MONTH, this.mDatePick.getMonth()); this.mCalendar.set(Calendar.DAY_OF_MONTH, this.mDatePick.getDayOfMonth()); this.mCalendar.set(Calendar.HOUR_OF_DAY, this.mTimePick.getCurrentHour().intValue()); this.mCalendar.set(Calendar.MINUTE, this.mTimePick.getCurrentMinute().intValue()); Log.v(TAG, "onClick is mOkView is click year : " + year + ", month : " + month + ", day : " + day + "\n" + ", hour : " + hour + ", minute : " + minute); Intent fakeCallIntent = new Intent(); fakeCallIntent.putExtra(EXTRA_TIME_MILLIS, this.mCalendar.getTimeInMillis()); setResult(RESULT_OK, fakeCallIntent); finish(); } else if (v == mCancelView) { Log.v(TAG, "onClick is mCancelView is click"); Intent fakeCallIntent = new Intent(); setResult(RESULT_OK, fakeCallIntent); finish(); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { setResult(RESULT_OK); SetupDateTimeActivity.this.finish(); return true; } return true; } @Override public void onDateChanged(DatePicker datePicker, int year, int month, int day) { Log.v(TAG, "onClick is mOkView is click year : " + year + ", month : " + month + ", day : " + day); } @Override public void onTimeChanged(TimePicker timePicker, int hour, int minute) { Log.v(TAG, "onTimeChanged i hour: " + hour + ", minute : " + minute); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/background" > <TextView android:id="@+id/setup_date_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:background="@drawable/title_bg" android:padding="5.0dip" android:text="@string/title_set_date_time" android:textColor="#ffdddddd" android:textSize="16.0sp" /> <ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/setup_date_title" > <RelativeLayout android:id="@+id/date_time_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5.0dip" android:padding="5.0dip" > <TextView android:id="@+id/date_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:maxLines="1" android:paddingBottom="5.0dip" android:text="@string/date_title" android:textColor="#ffffffff" android:textSize="16.0sp" /> <DatePicker android:id="@+id/setup_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/date_title" android:layout_centerHorizontal="true" /> <TextView android:id="@+id/setup_time_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/setup_date" android:maxLines="1" android:paddingBottom="5.0dip" android:text="@string/time_title" android:textColor="#ffffffff" android:textSize="16.0sp" /> <TimePicker android:id="@+id/setup_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/setup_time_title" android:layout_centerHorizontal="true" /> <LinearLayout android:id="@+id/button_menu_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/setup_time" android:layout_marginTop="20.0dip" android:orientation="horizontal" android:padding="5.0dip" > <Button android:id="@+id/left_ok" android:layout_width="fill_parent" android:layout_height="45.0dip" android:layout_marginRight="10.0dip" android:layout_weight="1.0" android:background="@drawable/button_bg" android:gravity="center" android:lines="1" android:padding="8.0dip" android:text="@string/done" android:textColor="#ff000000" /> <Button android:id="@+id/right_cancel" android:layout_width="fill_parent" android:layout_height="45.0dip" android:layout_weight="1.0" android:background="@drawable/button_bg" android:gravity="center" android:lines="1" android:padding="8.0dip" android:text="@string/cancel" android:textColor="#ff000000" /> </LinearLayout> </RelativeLayout> </ScrollView> </RelativeLayout>
CallingScreen.java
import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; import android.view.KeyEvent; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Chronometer; import android.widget.TextView; import android.widget.Toast; import android.widget.Chronometer.OnChronometerTickListener; public class CallingScreen extends Activity implements OnClickListener, OnChronometerTickListener{ private Button mEndButton; private Chronometer mCallRecordTimer; private TextView mShowCallNameTv; private TextView mShowCallNumberTv; private SharedPreferences mInCallScreenSharePred; private static final String PROFILE_KEY = "com.hy.fakecall_preferences"; private static final String SHOW_CALL_NAME = "show_call_name"; private static final String SHOW_CALL_NUMBER = "show_call_number"; private String mShowNameStr; private String mShowNumberStr; //hongyu hexiaoming add incall activity background music 20140306 start private MediaPlayer mMediaPlayer; private AudioManager mAudioManager; //hongyu hexiaoming add incall activity background music 20140306 end @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.calling_screen); final Window window = getWindow(); final WindowManager.LayoutParams lp = window.getAttributes(); // set this flag so this activity will let the Home Key Fail // set this flag so this activity will stay in front of the keyguard and // set the Screen on lp.flags |= WindowManager.LayoutParams.FLAG_HOMEKEY_DISPATCHED; window.setAttributes(lp); // SharedPreferences mInCallScreenSharePred = getSharedPreferences(PROFILE_KEY, Context.MODE_PRIVATE); mEndButton = (Button) findViewById(R.id.endButton); mEndButton.setOnClickListener(CallingScreen.this); mCallRecordTimer = (Chronometer) findViewById(R.id.callRecordTimer); mCallRecordTimer.setOnChronometerTickListener(this); mCallRecordTimer.setBase(SystemClock.elapsedRealtime()); mCallRecordTimer.start(); mShowCallNameTv = (TextView) findViewById(R.id.show_call_name); mShowCallNumberTv = (TextView) findViewById(R.id.show_call_number); mShowNameStr = mInCallScreenSharePred.getString(SHOW_CALL_NAME, getResources().getString(R.string.stranger_name)); mShowNumberStr = mInCallScreenSharePred.getString(SHOW_CALL_NUMBER, getResources().getString(R.string.stranger_number)); mShowCallNameTv.setText(mShowNameStr); mShowCallNumberTv.setText(mShowNumberStr); //hongyu hexiaoming add incall activity background music 20140306 start playBackgroundMusic(); //hongyu hexiaoming add incall activity background music 20140306 end } //hongyu hexiaoming add incall activity background music 20140306 start private void playBackgroundMusic() { boolean isCustomBgMusic = mInCallScreenSharePred.getBoolean(SetupBackgroundMusicActivity.IS_CUSTOM_BACKGROUND_MUSIC, false); if(isCustomBgMusic){ //Uri localUri = Uri.parse("content://settings/system/ringtone"); String path = mInCallScreenSharePred.getString(SetupBackgroundMusicActivity.BACKGROUND_MUSIC_PATH, null); Uri localUri = Uri.parse(path); this.mMediaPlayer = new MediaPlayer(); if (localUri == null) return; try { this.mMediaPlayer.setDataSource(this, localUri); if (((AudioManager) getSystemService(Context.AUDIO_SERVICE)).getStreamVolume(2) > 0) { this.mMediaPlayer.setAudioStreamType(2); this.mMediaPlayer.setLooping(true); this.mMediaPlayer.prepare(); this.mMediaPlayer.start(); } } catch (Exception localException) { return; } } } private void stopBackgroundMusic() { if (this.mMediaPlayer == null) return; this.mMediaPlayer.stop(); this.mMediaPlayer.release(); this.mMediaPlayer = null; } //hongyu hexiaoming add incall activity background music 20140306 end @Override protected void onDestroy() { super.onDestroy(); //hongyu hexiaoming add incall activity background music 20140306 start stopBackgroundMusic(); //hongyu hexiaoming add incall activity background music 20140306 end } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { return true; } return true; } @Override public void onClick(View v) { if (v == mEndButton) { CallingScreen.this.finish(); Toast.makeText(CallingScreen.this, R.string.end_call_screen_view, Toast.LENGTH_LONG).show(); } } @Override public void onChronometerTick(Chronometer chronometer) { // TODO Auto-generated method stub } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/top_show_call_info" android:layout_width="match_parent" android:layout_height="80dp" android:layout_alignParentTop="true" android:layout_above="@+id/show_incoming_image" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:orientation="horizontal" > <TextView android:id="@+id/show_call_number" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:gravity="left" android:text="@string/who_call_me" android:textColor="@color/white" android:textSize="16.0dip" android:layout_weight="1" android:textStyle="bold" /> <TextView android:id="@+id/show_call_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/who_call_me" android:textColor="@color/white" android:gravity="right" android:textSize="16.0dip" android:layout_weight="1" android:textStyle="bold" /> </LinearLayout> <TextView android:id="@+id/show_city_name" android:layout_width="fill_parent" android:layout_height="20dip" android:layout_marginTop="5dip" android:gravity="right" android:text="@string/show_city_name" android:textColor="@color/white" android:textSize="16.0dip" android:textStyle="bold" /> <Chronometer android:id="@+id/callRecordTimer" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dip" android:paddingLeft="10dip" android:gravity="left" android:textColor="@color/white" android:background="@color/light_blue_color" android:textSize="15.0sp" /> </LinearLayout> <ImageView android:id="@id/show_incoming_image" android:layout_width="match_parent" android:layout_height="312dip" android:scaleType="fitXY" android:contentDescription="@string/unkown_picture" android:src="@drawable/call_contacts" android:layout_above="@+id/show_three_button" /> <LinearLayout android:id="@id/show_three_button" android:layout_above="@+id/endButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:drawableTop="@drawable/ic_sound_speakerphone_holo_dark" android:text="@string/call_speaker_button" > </TextView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:drawableTop="@drawable/hy_ic_in_call_touch_keyboard_off" android:text="@string/touch_keyboard_button" > </TextView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:drawableTop="@drawable/hy_ic_in_call_touch_tools_off" android:text="@string/call_touch_tools_button" > </TextView> </LinearLayout> <Button android:id="@id/endButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dip" android:layout_marginBottom="10dip" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:background="@drawable/hy_incall_button_end" android:soundEffectsEnabled="false" /> </RelativeLayout>
PickContacts.java
import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.support.v4.widget.SimpleCursorAdapter; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; import android.util.Log; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.CursorAdapter; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.telephony.PhoneNumberUtils; public class PickContacts extends Activity implements AdapterView.OnItemClickListener, TextWatcher{ private static final String TAG = "PickContacts"; private static final boolean DEBUG = true; private static final String SELECT_CONTACT_NAME = "select_contact_name"; private static final String SELECT_CONTACT_NUMBER = "select_contact_number"; private static final String[] CONTACTS_PROJECTION; private static final Uri mQueryContactsUri; private ContactsAdapter mContactsAdapter; private EditText mSearchEditText; private TextView mContactCountTv; private ListView mContactsListView; static { String[] arrayOfString = new String[3]; arrayOfString[0] = "_id"; arrayOfString[1] = "display_name"; arrayOfString[2] = "data1"; CONTACTS_PROJECTION = arrayOfString; mQueryContactsUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; } @SuppressWarnings("deprecation") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.pick_contact); mContactCountTv = (TextView) findViewById(R.id.contact_count); mSearchEditText = (EditText) findViewById(R.id.search_box); // get Contacts Cursor Cursor cursor = getContentResolver().query( mQueryContactsUri, CONTACTS_PROJECTION, null, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); startManagingCursor(cursor); if (DEBUG) { Log.v(TAG, " onCreate() cursor : " + cursor); if (cursor != null) { Log.v(TAG, " onCreate() cursor.getCount() : " + cursor.getCount()); for(int j = 0; j < cursor.getColumnCount(); j ++ ){ Log.v(TAG, "onCreate() cursor.ColumnName is : " + cursor.getColumnName(j)); } } } mContactsAdapter = new ContactsAdapter(PickContacts.this, cursor); // set counts to mContactCountTv if (cursor != null) { mContactCountTv.setText(cursor.getCount() + getResources().getString(R.string.contact_counts)); } else { mContactCountTv.setText(0 + getResources().getString(R.string.contact_counts)); return; } mContactsListView = (ListView) findViewById(R.id.list); mContactsListView.setAdapter(mContactsAdapter); mContactsListView.setOnItemClickListener(PickContacts.this); mSearchEditText.addTextChangedListener(PickContacts.this); } private String getPhoneNumber(Cursor cursor) { String str1 = PhoneNumberUtils.stripSeparators(cursor.getString(2)); if (TextUtils.isEmpty(str1)) return ""; if (str1.startsWith("+86")) { return str1.substring("+86".length()); } else { return str1; } } private class ContactsAdapter extends CursorAdapter { private LayoutInflater mLayoutinflater; public ContactsAdapter(Context context, Cursor c) { super(context, c); mLayoutinflater = LayoutInflater.from(context); } @Override public void bindView(View view, Context context, Cursor cursor) { ContantsHolder contantsHolder = (ContantsHolder)view.getTag(); // set contactsName String strName = cursor.getString(1); contantsHolder.contansName.setText(strName); // set contactsNumber String strNumber = PickContacts.this.getPhoneNumber(cursor); if (DEBUG) { Log.v(TAG, "bindView() strNumber : " + strNumber); } contantsHolder.contantsNumber.setText(strNumber); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { LinearLayout linearLayout = (LinearLayout) mLayoutinflater.inflate( R.layout.contacts_item, null); ContantsHolder contantsHolder = new ContantsHolder(); contantsHolder.contansName = (TextView) linearLayout.findViewById(R.id.contact_name); contantsHolder.contantsNumber = (TextView) linearLayout.findViewById(R.id.contact_number); linearLayout.setTag(contantsHolder); return linearLayout; } public Cursor runQueryOnBackgroundThread(CharSequence paramCharSequence) { Uri localUri = PickContacts.mQueryContactsUri; if (DEBUG) { Log.v(TAG, "runQueryOnBackgroundThread() paramCharSequence : " + paramCharSequence); } if (!(TextUtils.isEmpty(paramCharSequence))) localUri = Uri .withAppendedPath( ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI, Uri.encode(paramCharSequence.toString())); return PickContacts.this.getContentResolver().query( localUri, CONTACTS_PROJECTION, null, null, ContactsContract.Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC"); } } public class ContantsHolder { private TextView contansName; private TextView contantsNumber; } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { setResult(RESULT_OK); PickContacts.this.finish(); return true; } return true; } @Override public void afterTextChanged(Editable arg0) { } @Override public void beforeTextChanged(CharSequence charS, int arg1, int arg2, int arg3) { } @Override public void onTextChanged(CharSequence charS, int arg1, int arg2, int arg3) { String str = charS.toString(); if (DEBUG) { Log.v(TAG, "onTextChanged() str : " + str); } this.mContactsAdapter.getFilter().filter(str, mContactsListView); } @Override public void onItemClick(AdapterView<?> adapterView, View v, int position, long l) { Cursor selectContactsCursor = this.mContactsAdapter.getCursor(); selectContactsCursor.moveToPosition(position); Intent fakeCallIntent = new Intent(); fakeCallIntent.putExtra(SELECT_CONTACT_NAME, selectContactsCursor.getString(1)); fakeCallIntent.putExtra(SELECT_CONTACT_NUMBER, selectContactsCursor.getString(2)); setResult(RESULT_OK, fakeCallIntent); finish(); } }
SetupBackgroundMusicActivity.java
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.database.Cursor; import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; public class SetupBackgroundMusicActivity extends Activity { public static final String TAG = "SetupBackgroundMusicActivity"; public static final String RECORD_FOLDER = "Recording"; private final ArrayList<HashMap<String, Object>> mArrlist = new ArrayList<HashMap<String, Object>>(); private final ArrayList<String> mNameList = new ArrayList<String>(); private final ArrayList<String> mPathList = new ArrayList<String>(); private final ArrayList<String> mTitleList = new ArrayList<String>(); private final ArrayList<String> mDurationList = new ArrayList<String>(); private final List<Integer> mIdList = new ArrayList<Integer>(); private List<Integer> mCheckedList = new ArrayList<Integer>(); private boolean isEmpty = true; private static final String PATH = "path"; private static final String DURATION = "duration"; private static final String FILE_NAME = "filename"; private static final String CREAT_DATE = "creatdate"; private static final String FORMAT_DURATION = "formatduration"; private static final String RECORD_ID = "recordid"; private static final int PATH_INDEX = 2; private static final int DURATION_INDEX = 3; private static final int CREAT_DATE_INDEX = 6; private static final int RECORD_ID_INDEX = 7; private static final int ONE_SECOND = 1000; private static final int TIME_BASE = 60; private ListView mRecordingFileListView; private TextView myEmptyTextView; private SharedPreferences mInCallScreenSharePred; private SharedPreferences.Editor mInCallScreenSharedEditor; private static final String PROFILE_KEY = "com.hy.fakecall_preferences"; public static final String IS_CUSTOM_BACKGROUND_MUSIC = "is_custom_background_music"; public static final String BACKGROUND_MUSIC_PATH = "background_music_path"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.pick_background_music); mInCallScreenSharePred = getSharedPreferences(PROFILE_KEY, Context.MODE_PRIVATE); mInCallScreenSharedEditor = mInCallScreenSharePred.edit(); mRecordingFileListView = (ListView) findViewById(R.id.list); myEmptyTextView = (TextView) findViewById(R.id.empty_view); mRecordingFileListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long itemId) { Log.i(TAG, "onItemClick:path----"+mPathList.get(position).toString()); mInCallScreenSharedEditor.putBoolean(IS_CUSTOM_BACKGROUND_MUSIC, true); mInCallScreenSharedEditor.putString(BACKGROUND_MUSIC_PATH, mPathList.get(position).toString()); mInCallScreenSharedEditor.commit(); //intent.setClass(this, FakeCallActivity.class); //setResult(RESULT_OK, intent); finish(); } }); QueryDataTask queryTask = new QueryDataTask(); queryTask.execute(); } /** * through AsyncTask to query recording file data from database */ public class QueryDataTask extends AsyncTask<Void, Object, ArrayList<HashMap<String, Object>>> { //List<Integer> mList; //QueryDataTask(List<Integer> list) { QueryDataTask() { //mList = list; } protected ArrayList<HashMap<String, Object>> doInBackground(Void... params) { return queryData(); } @Override protected void onPostExecute(ArrayList<HashMap<String, Object>> result) { } } public ArrayList<HashMap<String, Object>> queryData() { mArrlist.clear(); mNameList.clear(); mPathList.clear(); mTitleList.clear(); mDurationList.clear(); mIdList.clear(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(MediaStore.Audio.Media.IS_MUSIC); stringBuilder.append(" =0 and "); stringBuilder.append(MediaStore.Audio.Media.DATA); stringBuilder.append(" LIKE '%"); stringBuilder.append("/"); stringBuilder.append(RECORD_FOLDER); stringBuilder.append("%'"); String selection = stringBuilder.toString(); Cursor recordingFileCursor = getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[] { MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media.ALBUM, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.DURATION, MediaStore.Audio.Media.DISPLAY_NAME, MediaStore.Audio.Media.DATE_ADDED, MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media._ID },selection, null, null); try { if ((null == recordingFileCursor) || (0 == recordingFileCursor.getCount())) { Log.i(TAG, "<queryData> the data return by query is null"); return null; } recordingFileCursor.moveToFirst(); int num = recordingFileCursor.getCount(); final int sizeOfHashMap = 6; for (int j = 0; j < num; j++) { HashMap<String, Object> map = new HashMap<String, Object>(sizeOfHashMap); String path = recordingFileCursor.getString(PATH_INDEX); String fileName = null; if (null != path) { fileName = path.substring(path.lastIndexOf("/") + 1, path.length()); } int duration = recordingFileCursor.getInt(DURATION_INDEX); if (duration < ONE_SECOND) { duration = ONE_SECOND; } String createDate = recordingFileCursor.getString(CREAT_DATE_INDEX); int recordId = recordingFileCursor.getInt(RECORD_ID_INDEX); map.put(FILE_NAME, fileName); map.put(PATH, path); map.put(DURATION, duration); map.put(CREAT_DATE, createDate); map.put(FORMAT_DURATION, formatDuration(duration)); map.put(RECORD_ID, recordId); mNameList.add(fileName); mPathList.add(path); mTitleList.add(createDate); mDurationList.add(formatDuration(duration)); mIdList.add(recordId); recordingFileCursor.moveToNext(); mArrlist.add(map); } } catch (IllegalStateException e) { e.printStackTrace(); } finally { if (null != recordingFileCursor) { recordingFileCursor.close(); } } if(mArrlist.size() == 0){ isEmpty = true; }else{ isEmpty = false; } EditViewAdapter adapter = new EditViewAdapter(getApplicationContext(), mNameList, //mPathList, mTitleList, mDurationList, mIdList, list); mPathList, mTitleList, mDurationList, mIdList,null); mRecordingFileListView.setAdapter(adapter); if(isEmpty){ myEmptyTextView.setVisibility(View.VISIBLE); mRecordingFileListView.setVisibility(View.GONE); }else{ mRecordingFileListView.setVisibility(View.VISIBLE); myEmptyTextView.setVisibility(View.GONE); } return mArrlist; } /** * format duration to display as 00:00 * * @param duration * the duration to be format * @return the String after format */ private String formatDuration(int duration) { //String timerFormat = getResources().getString(R.string.timer_format); int time = duration / ONE_SECOND; //return String.format(timerFormat, time / TIME_BASE, time % TIME_BASE); return (time / TIME_BASE) + ":"+ (time % TIME_BASE); } }
1.Chronometer:
在Android中,可以使用计时器来实现对时间的监测,这个类所实现的功能有开始计时,停止计时,重新计时,设置计时模式
2.com.android.internal.widget.multiwaveview.GlowPadView
GlowPadView就是用来实现滑动接听的控件,该控件隶属InCallScreen界面,也就是我们拨打或接听电话的那个界面
3.TextWatcher:
Android TextWatcher监控EditText中的输入内容并限制其输入字符个数
4.CursorAdapter:
Cursor适配器,
5.MediaPlayer, AudioManager, Vibrator
播放音乐,同时振动