`
923723914
  • 浏览: 636554 次
文章分类
社区版块
存档分类
最新评论

Android项目实战--手机卫士15--设置手机归属地的样式以及显示位置

 
阅读更多

首先,先把我之前写的那个更新操作的一个bug修复先,这个bug就是在Android4以上,我们已经不能在主线程里面进行网络操作的啦,如果进行网络操作,就会报错

所以我们就要做一下改动,我们在onCreate方法里面开启一个线程,用来检测更新信息的

		new Thread()
		{
			public void run() 
			{
				try
				{
					UpdateInfoService updateInfoService = new UpdateInfoService(SplashActivity.this);
					info = updateInfoService.getUpdateInfo(R.string.serverUrl);
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			};
		}.start();


然后呢,就在原来的isNeedUpdate方法里面进行一些修改啦

	private boolean isNeedUpdate(String version)
	{
		if(info == null)
		{
			Toast.makeText(this, "获取更新信息异常,请稍后再试", Toast.LENGTH_SHORT).show();
			loadMainUI();
			return false;
		}
		String v = info.getVersion();
		if(v.equals(version))
		{
			Log.i(TAG, "当前版本:" + version);
			Log.i(TAG, "最新版本:" + v);
			loadMainUI();
			return false;
		}
		else
		{
			Log.i(TAG, "需要更新");
			return true;
		}
	}


好啦,到这里,我们的这个bug就修复的啦。在进入今天的内容之前,先谢谢一位网友啦,是他发现这个问题的,非常感谢!

好,我们今天要讲的就是设置手机归属地的样式以及显示位置,先上图,让大家看一下我们今天要做的效果

大家可以看到,我们今天要做的就是显示风格和位置,那个显示风格就是上面的第二张图片,其实这个功能很简单的,就是记录下来用户设置的风格,然后就进行一个背景的设置而已,而第二个要做的就是显示的位置啦,上面第三张图就是啦,我们把那个activity做成了透明的了,如果你觉得不好,那么也可以不做成透明的,我们可以手动那个紫色的方块,来确定要显示的位置!设置好这些之后,再把服务开启,我们就可以看到下面的效果的啦!

好,废话不多说,我们现在就开始做,我们首先把风格那个对话框给做出来

com.xiaobin.security.ui.AToolActivity

package com.xiaobin.security.ui;

import java.io.File;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.xiaobin.security.R;
import com.xiaobin.security.engine.DownloadTask;
import com.xiaobin.security.service.AddressService;

public class AToolActivity extends Activity implements OnClickListener
{
	private static final int ERROR = 0;
	private static final int SUCCESS = 1;
	
	private TextView tv_atool_query;
	private TextView tv_atool_number_service_state;
	private CheckBox cb_atool_state;
	private TextView tv_atool_select_bg;
	private TextView tv_atool_change_location;
	private Intent serviceIntent;
	private ProgressDialog pd;
	
	private SharedPreferences sp;
	
	@SuppressLint("HandlerLeak")
	private Handler handler = new Handler()
	{
		public void handleMessage(Message msg) 
		{
			switch(msg.what)
			{
				case ERROR : 
					Toast.makeText(AToolActivity.this, "下载数据库失败,请检查网络!", Toast.LENGTH_SHORT).show();
					break;
					
				case SUCCESS : 
					Toast.makeText(AToolActivity.this, "数据库下载成功!", Toast.LENGTH_SHORT).show();
					break;
					
				default : 
					break;
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.atool);
		
		sp = getSharedPreferences("config", Context.MODE_PRIVATE);
		
		tv_atool_query = (TextView) findViewById(R.id.tv_atool_query);
		tv_atool_query.setOnClickListener(this);
		
		tv_atool_select_bg = (TextView) findViewById(R.id.tv_atool_select_bg);
		tv_atool_select_bg.setOnClickListener(this);
		
		tv_atool_change_location = (TextView) findViewById(R.id.tv_atool_change_location);
		tv_atool_change_location.setOnClickListener(this);
		
		tv_atool_number_service_state = (TextView) findViewById(R.id.tv_atool_number_service_state);
		cb_atool_state = (CheckBox) findViewById(R.id.cb_atool_state);
		serviceIntent = new Intent(this, AddressService.class);
		cb_atool_state.setOnCheckedChangeListener(new OnCheckedChangeListener()
		{
			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
			{
				if(isChecked)
				{
					startService(serviceIntent);
					tv_atool_number_service_state.setTextColor(Color.BLACK);
					tv_atool_number_service_state.setText("归属地服务已开启");
				}
				else
				{
					stopService(serviceIntent);
					tv_atool_number_service_state.setTextColor(Color.RED);
					tv_atool_number_service_state.setText(R.string.number_service_state);
				}
			}
		});
	}

	@Override
	public void onClick(View v)
	{
		switch(v.getId())
		{
			case R.id.tv_atool_query : 
				query();
				break;
				
			case R.id.tv_atool_select_bg : 
				selectStyle();
				break;
				
			case R.id.tv_atool_change_location : 
				Intent intent = new Intent(this, DragViewActivity.class);
				startActivity(intent);
				break;
				
			default : 
				break;
		}
	}
	
	private void query()
	{
		if(isDBExist())
		{
			Intent intent = new Intent(this, QueryNumberActivity.class);
			startActivity(intent);
		}
		else
		{
			//提示用户下载数据库
			pd = new ProgressDialog(this);
			pd.setMessage("正在下载数据库...");
			pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			pd.setCancelable(false);
			pd.show();
			new Thread()
			{
				public void run() 
				{
					String path = getResources().getString(R.string.serverdb);
					File dir = new File(Environment.getExternalStorageDirectory(), "/security/db");
					if(!dir.exists())
					{
						dir.mkdirs();
					}
					String dbPath = Environment.getExternalStorageDirectory() + "/security/db/data.db";
					try
					{
						//这个类,我们在做更新apk的时候已经写好的啦,现在直接拿过来用就可以啦
						DownloadTask.getFile(path, dbPath, pd);
						pd.dismiss();
					}
					catch (Exception e)
					{
						e.printStackTrace();
						pd.dismiss();
						Message message = new Message();
						message.what = ERROR;
						handler.sendMessage(message);
					}
				};
			}.start();
		}
	}
	
	private boolean isDBExist()
	{
		if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
		{
			File file = new File(Environment.getExternalStorageDirectory() + "/security/db/data.db");
			if(file.exists())
			{
				return true;
			}
		}
		return false;
	}
	
	//显示风格的对话框,我准备了5张不同风格的背景图片,根据用户选择的风格不一样,设置不同的背景
	private void selectStyle()
	{
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle("归属地显示风格");
		String[] items = new String[] {"半透明", "活力橙", "苹果绿", "孔雀蓝", "金属灰"};
		builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener()
		{
			@Override
			public void onClick(DialogInterface dialog, int which)
			{
				Editor editor = sp.edit();
				editor.putInt("background", which);
				editor.commit();
			}
		});
		builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener()
		{
			@Override
			public void onClick(DialogInterface dialog, int which)
			{
				
			}
		});
		builder.create().show();
	}

}


我们写了一个方法,selectStyle这个方法会把用户的设置记录下来,然后我们就在显示那个归属地那里读取出来,设置一下背景就可以啦,但我们现在先把那个显示位置的也做出来先

其实这个也很简单的,我们就用一个onTouch事件,然后记录下最终的位置就可以的啦

com.xiaobin.security.ui.DragViewActivity

package com.xiaobin.security.ui;

import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;

import com.xiaobin.security.R;

public class DragViewActivity extends Activity implements OnTouchListener
{
	private ImageView iv_drag_location;
	private SharedPreferences sp;
	
	//记录第一次触摸的坐标
	private int startX;
	private int startY;
	
	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		setContentView(R.layout.drag_view);
		
		sp = getSharedPreferences("config", Context.MODE_PRIVATE);
		
		iv_drag_location = (ImageView) findViewById(R.id.iv_drag_location);
		iv_drag_location.setOnTouchListener(this);
	}
	
	@Override
	protected void onResume()
	{
		super.onResume();
		
		//加载上次移动的效果
		int x = sp.getInt("lastX", 0);
		int y = sp.getInt("lastY", 0);
		/*iv_drag_location.layout(iv_drag_location.getLeft() + x, iv_drag_location.getTop() + y, 
				iv_drag_location.getRight() + x, iv_drag_location.getBottom() + y);
		iv_drag_location.invalidate();*/
		RelativeLayout.LayoutParams params = (LayoutParams) iv_drag_location.getLayoutParams();
		params.leftMargin = x;
		params.topMargin = y;
		iv_drag_location.setLayoutParams(params);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event)
	{
		switch(v.getId())
		{
			case R.id.iv_drag_location : 
				switch(event.getAction())
				{
					case MotionEvent.ACTION_DOWN : 
						startX = (int) event.getRawX();
						startY = (int) event.getRawY();
						break;
						
					case MotionEvent.ACTION_MOVE : 
						int x = (int) event.getRawX();
						int y = (int) event.getRawY();
						
						//算出移动距离
						int dx = x - startX;
						int dy = y - startY;
						int l = iv_drag_location.getLeft();
						int r = iv_drag_location.getRight();
						int t = iv_drag_location.getTop();
						int b = iv_drag_location.getBottom();
						
						//设置新的布局位置
						iv_drag_location.layout(l + dx, t + dy, r + dx, b + dy);
						
						//重新获取位置
						startX = (int) event.getRawX();
						startY = (int) event.getRawY();
						break;
						
					case MotionEvent.ACTION_UP : 
						int lastX = iv_drag_location.getLeft();
						int lastY = iv_drag_location.getTop();
						Editor editor = sp.edit();
						editor.putInt("lastX", lastX);
						editor.putInt("lastY", lastY);
						editor.commit();
						break;
						
					default : 
						break;
				}
				break;
				
			default : 
				break;
		}
		return true;
	}

}


好啦,写完这两个,我们就可以回到我们之前显示归属地的那个Service里面写逻辑啦

com.xiaobin.security.service.AddressService

package com.xiaobin.security.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.xiaobin.security.R;
import com.xiaobin.security.engine.NumberAddressService;

public class AddressService extends Service
{
	private TelephonyManager telephonyManager;
	private MyPhoneListener listener;
	private WindowManager windowManager;
	private View view;
	
	private SharedPreferences sp;

	@Override
	public IBinder onBind(Intent intent)
	{
		return null;
	}
	
	@Override
	public void onCreate()
	{
		super.onCreate();
		
		sp = getSharedPreferences("config", Context.MODE_PRIVATE);
		
		windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
		listener = new MyPhoneListener();
		telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
	}
	
	@Override
	public void onDestroy()
	{
		super.onDestroy();
		//停止监听
		telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE);
	}
	
	//显示归属地的窗体
	private void showLocation(String address)
	{
		WindowManager.LayoutParams params = new WindowManager.LayoutParams();
		params.width = WindowManager.LayoutParams.WRAP_CONTENT;
		params.height = WindowManager.LayoutParams.WRAP_CONTENT;
		params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE //无法获取焦点
				| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE //无法点击
				| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;//保持屏幕亮
		params.format = PixelFormat.TRANSLUCENT;//设置成半透明的
		params.type = WindowManager.LayoutParams.TYPE_TOAST;
		params.setTitle("Toast");
		
		//主要是确定坐标系是从左上角开始的,不然呆会设置位置的时候有些麻烦
		params.gravity = Gravity.LEFT | Gravity.TOP;
		params.x = sp.getInt("lastX", 0);
		params.y = sp.getInt("lastY", 0);
		
		view = View.inflate(getApplicationContext(), R.layout.show_location, null);
		LinearLayout ll = (LinearLayout) view.findViewById(R.id.ll_location);
		int type = sp.getInt("background", 0);
		switch(type)
		{
			case 0 : 
				ll.setBackgroundResource(R.drawable.call_locate_white);
				break;
				
			case 1 : 
				ll.setBackgroundResource(R.drawable.call_locate_orange);
				break;
				
			case 2 : 
				ll.setBackgroundResource(R.drawable.call_locate_green);
				break;
				
			case 3 : 
				ll.setBackgroundResource(R.drawable.call_locate_blue);
				break;
				
			case 4 : 
				ll.setBackgroundResource(R.drawable.call_locate_gray);
				break;
				
			default : 
				break;
		}
		
		TextView tv = (TextView) view.findViewById(R.id.tv_show_location);
		tv.setText("归属地: " + address);
		windowManager.addView(view, params);
	}
	
	//========================================================================
	
	private class MyPhoneListener extends PhoneStateListener
	{
		@Override
		public void onCallStateChanged(int state, String incomingNumber)
		{
			super.onCallStateChanged(state, incomingNumber);
			
			switch(state)
			{
				case TelephonyManager.CALL_STATE_IDLE : //空闲状态
					if(view != null)
					{
						windowManager.removeView(view);//移除显示归属地的那个view
						view = null;
					}
					break;
					
				case TelephonyManager.CALL_STATE_OFFHOOK : //接通电话
					if(view != null)
					{
						windowManager.removeView(view);//移除显示归属地的那个view
						view = null;
					}
					break;
					
				case TelephonyManager.CALL_STATE_RINGING : //铃响状态
					String address = NumberAddressService.getAddress(incomingNumber);
					showLocation(address);
					break;
					
				default : 
					break;
			}
		}
	}

}


好啦,到现在为止,我们的显示风格还有显示位置就已经全部完成的啦!下次我们就会讲高级工具里面的黑名单功能的啦!

今天源码下载

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics