首先,先把我之前写的那个更新操作的一个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;
}
}
}
}
好啦,到现在为止,我们的显示风格还有显示位置就已经全部完成的啦!下次我们就会讲高级工具里面的黑名单功能的啦!