Android实现获取系统应用列表

Android系统为我们提供了很多服务管理的类,包括ActivityManager、PowerManager(电源管理)、AudioManager(音频管理) 等。除此之外,还提供了一个PackageManger管理类,它的主要职责是管理应用程序包。 通过它,我们就可以获取应用程序信息。  

PackageManager的功能: 

•安装,卸载应用

•查询permission相关信息

•查询Application相关信息(application,activity,receiver,service,provider及相应属性等)

•查询已安装应用

•增加,删除permission

•清除用户数据、缓存,代码段等

我们可以用PackageManager来显示系统安装的应用程序列表或者系统程序列表  

相关类的介绍

PackageItemInfo类

说明: AndroidManifest.xml文件中所有节点的基类,提供了这些节点的基本信息:a label、icon、 meta-data。它并不 直接使用,而是由子类继承然后调用相应方法。

常用字段:

public int icon 获得该资源图片在R文件中的值 (对应于android:icon属性)

public int labelRes 获得该label在R文件中的值(对应于android:label属性)

public String name 获得该节点的name值 (对应于android:name属性)

public String packagename 获得该应用程序的包名 (对应于android:packagename属性)

常用方法:

Drawable loadIcon(PackageManager pm) 获得当前应用程序的图像

CharSequence loadLabel(PackageManager pm) 获得当前应用程序的label

ActivityInfo类

继承自 PackageItemInfo

说明: 获得应用程序中<activity/>或者 <receiver />节点的信息 。

我们可以通过它来获取我们设置的任何属性,包括 theme 、launchMode、launchmode等

常用方法继承至PackageItemInfo类中的loadIcon()和loadLabel()

ServiceInfo 类

说明: 同ActivityInfo类似 ,同样继承自 PackageItemInfo,只不过它表示的是<service>节点信息。

ApplicationInfo类

继承自 PackageItemInfo

说明:获取一个特定引用程序中<application>节点的信息。

字段说明:    

flags字段: FLAG_SYSTEM 系统应用程序        

FLAG_EXTERNAL_STORAGE 表示该应用安装在sdcard中

常用方法继承至PackageItemInfo类中的loadIcon()和loadLabel()

ResolveInfo类

说明:根据<intent>节点来获取其上一层目录的信息,通常是<activity>、<receiver>、<service>节点信息。

常用字段:

public ActivityInfo activityInfo 获取 ActivityInfo对象,即<activity>或<receiver >节点信息

public ServiceInfo serviceInfo 获取 ServiceInfo对象,即<activity>节点信息

常用方法:

Drawable loadIcon(PackageManager pm) 获得当前应用程序的图像

CharSequence loadLabel(PackageManager pm) 获得当前应用程序的label

PackageInfo类

说明:手动获取AndroidManifest.xml文件的信息 。

常用字段:

public String packageName 包名

public ActivityInfo[] activities 所有<activity>节点信息

public ApplicationInfo applicationInfo <application>节点信息,只有一个

public ActivityInfo[] receivers 所有<receiver>节点信息,多个

public ServiceInfo[] services 所有<service>节点信息 ,多个

PackageManger 类

说明: 获得已安装的应用程序信息 。

可以通过getPackageManager()方法获得。

常用方法:

public abstract PackageManager getPackageManager()

功能:获得一个PackageManger对象

public abstrac tDrawable getApplicationIcon(StringpackageName)

参数: packageName 包名

功能:返回给定包名的图标,否则返回null

public abstract ApplicationInfo getApplicationInfo(String packageName, int flags)

参数:packagename 包名 flags 该ApplicationInfo是此flags标记,通常可以直接赋予常数0即可

功能:返回该ApplicationInfo对象

public abstract List<ApplicationInfo> getInstalledApplications(int flags)

参数:flag为一般为GET_UNINSTALLED_PACKAGES,那么此时会返回所有ApplicationInfo。

我们可以对ApplicationInfo 的flags过滤,得到我们需要的。

功能:返回给定条件的所有PackageInfo

public abstract List<PackageInfo> getInstalledPackages(int flags)

参数如上

功能:返回给定条件的所有PackageInfo

public abstractResolveInfo resolveActivity(Intent intent, int flags)

参数: intent 查寻条件,Activity所配置的action和category flags: MATCH_DEFAULT_ONLY :Category必须带有CATEGORY_DEFAULT的Activity,才匹配 GET_INTENT_FILTERS :匹配Intent条件即可 GET_RESOLVED_FILTER :匹配Intent条件即可 功能 :返回给定条件的ResolveInfo对象(本质上是Activity)

public abstract List<ResolveInfo> queryIntentActivities(Intent intent, int flags)

参数同上

功能 :返回给定条件的所有ResolveInfo对象(本质上是Activity),集合对象

public abstract ResolveInfo resolveService(Intent intent, int flags)

参数同上

  功能 :返回给定条件的ResolveInfo对象(本质上是Service)

public abstract List<ResolveInfo> queryIntentServices(Intent intent, int flags)

参数同上

功能 :返回给定条件的所有ResolveInfo对象(本质上是Service),集合对象

  运行示例如下图所示:

示例代码:
项目工程结构图:

MainActivity:

package com.manager.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

/**
* 使用PackManager示例
* @Description: 获取Android系统应用程序

* @FileName: MainActivity.java

* @Package com.manager.test

* @Version V1.0
*/
public class MainActivity extends Activity {
private ListView lv;
private MyAdapter adapter;
ArrayList<HashMap<String, Object>> items = new ArrayList<HashMap<String, Object>>();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

lv = (ListView)findViewById(R.id.lv);

//得到PackageManager对象
PackageManager pm = getPackageManager();

//得到系统安装的所有程序包的PackageInfo对象
//List<ApplicationInfo> packs = pm.getInstalledApplications(0);
List<PackageInfo> packs = pm.getInstalledPackages(0);

for(PackageInfo pi:packs){
HashMap<String, Object> map = new HashMap<String, Object>();
////显示用户安装的应用程序,而不显示系统程序
// if((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM)==0&&
// (pi.applicationInfo.flags&ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)==0){
////这将会显示所有安装的应用程序,包括系统应用程序
// map.put(“icon”, pi.applicationInfo.loadIcon(pm));//图标
// map.put(“appName”, pi.applicationInfo.loadLabel(pm));//应用程序名称
// map.put(“packageName”, pi.applicationInfo.packageName);//应用程序包名
//
////循环读取并存到HashMap中,再增加到ArrayList上,一个HashMap就是一项
// items.add(map);
// }

//这将会显示所有安装的应用程序,包括系统应用程序
map.put(“icon”, pi.applicationInfo.loadIcon(pm));//图标
map.put(“appName”, pi.applicationInfo.loadLabel(pm));//应用程序名称
map.put(“packageName”, pi.applicationInfo.packageName);//应用程序包名

//循环读取并存到HashMap中,再增加到ArrayList上,一个HashMap就是一项
items.add(map);
}

/**
* 参数:Context
* ArrayList(item的集合)
* item的layout
* 包含ArrayList中的HashMap的key的数组
* key所对应的值的相应的控件id
*/
adapter = new MyAdapter(this, items, R.layout.list_item,
new String[]{“icon”, “appName”, “packageName”},
new int[]{R.id.icon, R.id.appName, R.id.packageName});

lv.setAdapter(adapter);
}
}

/**
* 自定义适配器
* @Description:自定义适配器

* @FileName: MainActivity.java

* @Package com.manager.test

* @Author Hanyongjian

* @Date 2012-3-6 上午08:42:48

* @Version V1.0
*/
class MyAdapter extends SimpleAdapter
{
private int[] appTo;
private String[] appFrom;
private ViewBinder appViewBinder;
private List<? extends Map<String, ?>> appData;
private int appResource;
private LayoutInflater appInflater;

/**
* 构造器
* @param context
* @param data
* @param resource
* @param from
* @param to
*/
public MyAdapter(Context context, List<? extends Map<String, ?>> data,
int resource, String[] from, int[] to) {
super(context, data, resource, from, to);
appData = data;
appResource = resource;
appFrom = from;
appTo = to;
appInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public View getView(int position, View convertView, ViewGroup parent){
return createViewFromResource(position, convertView, parent, appResource);
}

private View createViewFromResource(int position, View convertView, ViewGroup parent, int resource){
View v;

if(convertView == null){
v = appInflater.inflate(resource, parent,false);
final int[] to = appTo;
final int count = to.length;
final View[] holder = new View[count];

for(int i = 0; i < count; i++){
holder[i] = v.findViewById(to[i]);
}

v.setTag(holder);
}else {
v = convertView;
}

bindView(position, v);
return v;
}

private void bindView(int position, View view){
final Map dataSet = appData.get(position);

if(dataSet == null){
return;
}

final ViewBinder binder = appViewBinder;
final View[] holder = (View[])view.getTag();
final String[] from = appFrom;
final int[] to = appTo;
final int count = to.length;

for(int i = 0; i < count; i++){
final View v = holder[i];

if(v != null){
final Object data = dataSet.get(from[i]);
String text = data == null ? “”:data.toString();

if(text == null){
text = “”;
}

boolean bound = false;

if(binder != null){
bound = binder.setViewValue(v, data, text);
}

if(!bound){
/**
* 自定义适配器,关在在这里,根据传递过来的控件以及值的数据类型,
* 执行相应的方法,可以根据自己需要自行添加if语句。另外,CheckBox等
* 集成自TextView的控件也会被识别成TextView,这就需要判断值的类型
*/
if(v instanceof TextView){
//如果是TextView控件,则调用SimpleAdapter自带的方法,设置文本
setViewText((TextView)v, text);
}else if(v instanceof ImageView){
//如果是ImageView控件,调用自己写的方法,设置图片
setViewImage((ImageView)v, (Drawable)data);
}else {
throw new IllegalStateException(v.getClass().getName() + ” is not a ” +
“view that can be bounds by this SimpleAdapter”);
}
}
}
}
}

public void setViewImage(ImageView v, Drawable value)
{
v.setImageDrawable(value);
}
}

main.xml:

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”vertical” android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>

<ListView
android:id=”@+id/lv”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
</ListView>

</LinearLayout>

Android代码通过包名调用系统卸载程序

/**
 * 卸载指定包名的应用
 * @param packageName
*/
public boolean uninstall(String packageName) {
    boolean b = checkApplication(packageName);
    Logger.d(TAG, "Test:check:"+b);
    if (b) {
        Uri packageURI = Uri.parse("package:".concat(packageName));
        Intent intent = new Intent(Intent.ACTION_DELETE);
        intent.setData(packageURI);
        startActivity(intent);
        return true;
    }
    return false;
}

/**
 * 判断该包名的应用是否安装
 *
 * @param packageName
* @return
*/
private boolean checkApplication(String packageName) {
    Logger.d(TAG, "Test,run");
    if (packageName == null || "".equals(packageName)) {
        return false;
    }
    try {
        getPackageManager().getApplicationInfo(packageName,
                PackageManager.MATCH_UNINSTALLED_PACKAGES);
        return true;
    } catch (PackageManager.NameNotFoundException e) {
        Logger.e(TAG, "Test:"+e.toString());
    }
    return false;
}

Android~adb卸载系统预装应用

本文介绍一种安卓卸载系统应用的方法,如果你和我一样喜欢瞎折腾,有那么一点强迫症,希望对你有用。作为一名安卓开发者,大学以前总喜欢刷不同刷机包(ROM)、爱装不同的Launcher桌面体验,不过工作了没以前爱折腾了。安卓提供的adb工具不用多介绍,网上都有很多教程。

一. 实验条件

  • LG V30 (Android 9.0)
  • 较新adb驱动
  • PC一台
  • 对应的USB调试线一根

二. 安装adb驱动

下载360手机助手,安装USB连接手机,360手机助手对手机adb驱动支持很好,直接连接就好了。确定adb驱动安装好后,任务管理器将360Mobile相关的进程干掉。重新连接adb,最后使用cmd或者AS自带的Terminal进入命令行,熟悉我们的adb命令就行了。

三. adb卸载预装应用步骤

1、查看adb版本

确认adb版本较新,我自己亲自试了在自己笔记本电脑adb工具执行命令用不了,总是提示如下打印:

F:\mypc>adb devices
adb server is out of date. killing…
daemon started successfully *
List of devices attached
810e909e offline

尝试了网上的方法,还是没有解决,但想到公司电脑好像没有问题的。于是对比了两台电脑adb的版本,还是存在差异,或许是adb安装路径有问题!

F:\mypc>adb version
Android Debug Bridge version 1.0.29

E:\other>adb version
Android Debug Bridge version 1.0.41
Version 29.0.1-5644136
Installed as C:\Windows\system32\adb.exe

2、查看系统中所有包

执行下面命令,将打印复制到记事本中,方便后面查找。

adb shell pm list packages

3、确认不知名的应用包名(较低安卓版本可直接查看应用包名)

有的应用我们可以通过包名就可以判断哪一个应用,但有的应用我们是确定不了的。那么就需要确认当前运行的应用的包名,记住安卓Activity和Application packagename是有关系的!好几种方法,一种不行尝试另外一种哦。
法一:

1、在手机上打开app
2、执行:adb shell dumpsys window w |findstr / |findstr name=

法二:

1、在手机上打开app
2、执行:adb shell dumpsys activity activities
3、分析打印

执行:adb shell dumpsys activity activities 后,我拿到的打印如下,具体分析我们就知道包名和应用名是哪一个了。这条命令会将activity堆栈信息和活动信息告诉我们。

D:\other>adb shell dumpsys activity activities
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
Stack #102: type=standard mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 – 0, 0)
Task id #3162
mBounds=Rect(0, 0 – 0, 0)
mMinWidth=-1
mMinHeight=-1
mLastNonFullscreenBounds=null
* TaskRecord{5546a0e #3162 A=com.uplus.onphone U=0 StackId=102 sz=1}
userId=0 effectiveUid=u0a265 mCallingUid=u0a121 mUserSetupComplete=true mCallingPackage=com.lge.launcher3
affinity=com.uplus.onphone
intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.uplus.onphone/.activity.MainActivity}
realActivity=com.uplus.onphone/.activity.MainActivity
autoRemoveRecents=false isPersistable=true numFullscreen=1 activityType=1
rootWasReset=true mNeverRelinquishIdentity=true mReuseTask=false mLockTaskAuth=LOCK_TASK_AUTH_PINNABLE
Activities=[ActivityRecord{64b2438 u0 com.uplus.onphone/.activity.MainActivity t3162}]
askedCompatMode=false inRecents=true isAvailable=true
mRootProcess=ProcessRecord{d749b7 25828:com.uplus.onphone/u0a265}
stackId=102
hasBeenVisible=true mResizeMode=RESIZE_MODE_RESIZEABLE mSupportsPictureInPicture=false isResizeable=true lastActiveTime=95850170 (inactive for 12s)
* Hist #0: ActivityRecord{64b2438 u0 com.uplus.onphone/.activity.MainActivity t3162}
packageName=com.uplus.onphone processName=com.uplus.onphone
launchedFromUid=10121 launchedFromPackage=com.lge.launcher3 userId=0
app=ProcessRecord{d749b7 25828:com.uplus.onphone/u0a265}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.uplus.onphone/.activity.MainActivity bnds=[312,1214][584,1665] (has
extras) }
frontOfTask=true task=TaskRecord{5546a0e #3162 A=com.uplus.onphone U=0 StackId=102 sz=1}
taskAffinity=com.uplus.onphone
realActivity=com.uplus.onphone/.activity.MainActivity
baseDir=/system/product/app/UplusTVonPhone/UplusTVonPhone.apk
dataDir=/data/user/0/com.uplus.onphone
stateNotNeeded=false componentSpecified=true mActivityType=standard
compat={640dpi, } labelRes=0x7f12002d icon=0x7f0f0002 theme=0x7f13000a
mLastReportedConfigurations:
mGlobalConfig={1.0 460mcc1mnc [zh_CN_#Hans,en_US,zh_CN] ldltr sw360dp w360dp h654dp 640dpi nrml long hdr port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 – 27
12, 1440) mAppBounds=Rect(0, 0 – 1440, 2712) mWindowingMode=fullscreen mActivityType=undefined} s.45 fontTypeIndex0 forceEmbolden0}
mOverrideConfig={1.0 460mcc1mnc [zh_CN_#Hans,en_US,zh_CN] ldltr sw360dp w360dp h654dp 640dpi nrml long hdr port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 –
1440, 2712) mAppBounds=Rect(0, 0 – 1440, 2712) mWindowingMode=fullscreen mActivityType=standard} s.45 fontTypeIndex0 forceEmbolden0}
CurrentConfiguration={1.0 460mcc1mnc [zh_CN_#Hans,en_US,zh_CN] ldltr sw360dp w360dp h654dp 640dpi nrml long hdr port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0,
0 – 1440, 2712) mAppBounds=Rect(0, 0 – 1440, 2712) mWindowingMode=fullscreen mActivityType=standard} s.45 fontTypeIndex0 forceEmbolden0}
taskDescription: label=“null” icon=null iconResource=0 iconFilename=null primaryColor=ffffffff
backgroundColor=fffafafa
statusBarColor=ff000000
navigationBarColor=ff000000
launchFailed=false launchCount=1 lastLaunchTime=-2m33s40ms
haveState=false icicle=null
state=RESUMED stopped=false delayedResume=false finishing=false focused=true
keysPaused=false inHistory=true visible=true sleeping=false idle=true mStartingWindowState=STARTING_WINDOW_REMOVED
fullscreen=true noDisplay=false immersive=false launchMode=0
frozenBeforeDestroy=false forceNewConfig=false
mActivityType=standard
waitingVisible=false nowVisible=true lastVisibleTime=-12s404ms
connections=[ConnectionRecord{b2a7614 u0 CR com.uplus.onphone/.player.PopupPlayer:@b109867}]
resizeMode=RESIZE_MODE_RESIZEABLE
mLastReportedMultiWindowMode=false mLastReportedPictureInPictureMode=false
translucent=false
Running activities (most recent first):
TaskRecord{5546a0e #3162 A=com.uplus.onphone U=0 StackId=102 sz=1}
Run #0: ActivityRecord{64b2438 u0 com.uplus.onphone/.activity.MainActivity t3162}
mResumedActivity: ActivityRecord{64b2438 u0 com.uplus.onphone/.activity.MainActivity t3162}
mLastPausedActivity: ActivityRecord{64b2438 u0 com.uplus.onphone/.activity.MainActivity t3162}
Stack #0: type=home mode=fullscreen
isSleeping=false
mBounds=Rect(0, 0 – 0, 0)

法三:

1、手机打开应用
2、执行:adb shell dumpsys activity top
linux: adb shell dumpsys activity | grep “mFocusedActivity”
windows: adb shell dumpsys activity | findstr “mFocusedActivity”

这种方法和法二类似,但仔细看一下下面的打印太恐怖了。我打印了安卓Launcher桌面活动信息,居然什么都暴露了,我擦谷歌爸爸太强大了!

D:\other>adb shell dumpsys activity top
TASK com.android.systemui id=3064 userId=0
ACTIVITY com.android.systemui/.recents.RecentsActivity 1c13a90 pid=2533
Local Activity ca56c1a State:
mResumed=false mStopped=true mFinished=false
mChangingConfigurations=false
mCurrentConfig={1.0 460mcc1mnc [zh_CN_#Hans,en_US,zh_CN] ldltr sw360dp w360dp h654dp 640dpi nrml long hdr port finger -keyb/v/h -nav/h winConfig={ mBounds=Rect(0, 0 – 2712,1440) mAppBounds=Rect(0, 0 – 1440, 2712) mWindowingMode=fullscreen mActivityType=recents} s.45 fontTypeIndex0 forceEmbolden0}
mLoadersStarted=true
FragmentManager misc state:
mHost=android.app.ActivityH o s t C a l l b a c k s @ d f 5 b 1 f e m C o n t a i n e r = a n d r o i d . a p p . A c t i v i t y HostCallbacks@df5b1fe mContainer=android.app.ActivityHostCallbacks@df5b1femContainer=android.app.ActivityHostCallbacks@df5b1fe
mCurState=3 mStateSaved=true mDestroyed=false
ViewRoot:
mAdded=true mRemoved=false
mConsumeBatchedInputScheduled=false
mConsumeBatchedInputImmediatelyScheduled=false
mPendingInputEventCount=0
mProcessInputEventsScheduled=false
mTraversalScheduled=false mIsAmbientMode=false
android.view.ViewRootImplN a t i v e P r e I m e I n p u t S t a g e : m Q u e u e L e n g t h = 0 a n d r o i d . v i e w . V i e w R o o t I m p l NativePreImeInputStage: mQueueLength=0 android.view.ViewRootImplNativePreImeInputStage:mQueueLength=0android.view.ViewRootImplImeInputStage: mQueueLength=0
android.view.ViewRootImplKaTeX parse error: Expected ‘}’, got ‘#’ at position 338: …….I. 0,0-0,0 #̲102018a android…HostCallbacks@de35f9e
mContainer=android.app.ActivityH o s t C a l l b a c k s @ d e 35 f 9 e m C u r S t a t e = 5 m S t a t e S a v e d = f a l s e m D e s t r o y e d = f a l s e V i e w R o o t : m A d d e d = t r u e m R e m o v e d = f a l s e m C o n s u m e B a t c h e d I n p u t S c h e d u l e d = f a l s e m C o n s u m e B a t c h e d I n p u t I m m e d i a t e l y S c h e d u l e d = f a l s e m P e n d i n g I n p u t E v e n t C o u n t = 0 m P r o c e s s I n p u t E v e n t s S c h e d u l e d = f a l s e m T r a v e r s a l S c h e d u l e d = f a l s e m I s A m b i e n t M o d e = f a l s e a n d r o i d . v i e w . V i e w R o o t I m p l HostCallbacks@de35f9e mCurState=5 mStateSaved=false mDestroyed=false ViewRoot: mAdded=true mRemoved=false mConsumeBatchedInputScheduled=false mConsumeBatchedInputImmediatelyScheduled=false mPendingInputEventCount=0 mProcessInputEventsScheduled=false mTraversalScheduled=false mIsAmbientMode=false android.view.ViewRootImplHostCallbacks@de35f9emCurState=5mStateSaved=falsemDestroyed=falseViewRoot:mAdded=truemRemoved=falsemConsumeBatchedInputScheduled=falsemConsumeBatchedInputImmediatelyScheduled=falsemPendingInputEventCount=0mProcessInputEventsScheduled=falsemTraversalScheduled=falsemIsAmbientMode=falseandroid.view.ViewRootImplNativePreImeInputStage: mQueueLength=0
android.view.ViewRootImplI m e I n p u t S t a g e : m Q u e u e L e n g t h = 0 a n d r o i d . v i e w . V i e w R o o t I m p l ImeInputStage: mQueueLength=0 android.view.ViewRootImplImeInputStage:mQueueLength=0android.view.ViewRootImplNativePostImeInputStage: mQueueLength=0
Choreographer:
mFrameScheduled=false
mLastFrameTime=74902929 (9414 ms ago)
View Hierarchy:
DecorView@3260a7f[LauncherExtension]
android.widget.LinearLayout{c10568 V.E… … 0,0-1440,2880}
android.view.ViewStub{b9f5a4c G.E… …I. 0,0-0,0 #102018a android:id/action_mode_bar_stub}
android.widget.FrameLayout{1d23605 V.E… … 0,0-1440,2880 #1020002 android:id/content}
com.android.launcher3.LauncherRootView{6ee4c6f V.E… … 0,0-1440,2880 #7f0900a4 app:id/launcher}
android.widget.ImageView{d4f0c87 G.ED… …I. 0,0-0,0 #7f09002b app:id/blur_background_in_bottom_of_rootview}
com.android.launcher3.dragndrop.DragLayer{4f5ef54 V.E… … 0,0-1440,2880 #7f090056 app:id/drag_layer}
com.android.launcher3.FocusIndicatorView{324ca95 V.ED… … 0,96-208,304 #7f090064 app:id/focus_indicator}
com.android.launcher3.Workspace{7e3a7b4 V.ED…L. … -2909,-2189-4349,5069 #7f090163 app:id/workspace}
com.android.launcher3.CellLayout{54a0481 VFED…CL. … 2949,2365-4309,4469}
android.widget.LinearLayout{a1d7aa I.E… … 0,0-0,0}
android.widget.ImageButton{c1acf9b VFED…C… …I. 0,0-0,0}
com.android.launcher3.ClickShadowView{f8dcf38 V.ED… … 0,0-320,468}
com.android.launcher3.ShortcutAndWidgetContainer{1d47b11 V.E… … 0,0-1360,2104}
FolderIcon {手机管理}
android.widget.ImageView{51dc476 V.ED… … 8,6-264,262 #7f0900ec app:id/preview_background}
AppIcon {手机管理}
AppIcon {联系人}
AppIcon {文件管理器}
AppIcon {计算器}
AppIcon {Quick备忘录+}
AppIcon {设置}
com.android.launcher3.CellLayout{18f8967 VFED…CL. … 4389,2365-5749,4469}
android.widget.LinearLayout{8ccca77 I.E… … 0,0-0,0}
android.widget.ImageButton{3eca6e4 VFED…C… …I. 0,0-0,0}
com.android.launcher3.ClickShadowView{ef4b74d V.ED… … 0,0-320,468}
com.android.launcher3.ShortcutAndWidgetContainer{99b202 V.E… … 0,0-1360,2104}
AppIcon {豌豆荚}
AppIcon {支付宝}
AppIcon {百度网盘}
AppIcon {微信}
AppIcon {高德地图}
AppIcon {美团}
AppIcon {QQ}
AppIcon {优酷视频}
AppIcon {网易云音乐}
AppIcon {手机淘宝}
AppIcon {王者荣耀}
AppIcon {当当}
AppIcon {迅雷}
AppIcon {WiFi万能钥匙}
AppIcon {发现精彩}
AppIcon {LBE安全大师}
AppIcon {Chrome}
com.android.launcher3.CellLayout{815503 VFED…CL. … 5829,2365-7189,4469}
android.widget.LinearLayout{5399713 I.E… … 0,0-0,0}
android.widget.ImageButton{13f4d50 VFED…C… …I. 0,0-0,0}
com.android.launcher3.ClickShadowView{d627b49 V.ED… … 0,0-320,468}
com.android.launcher3.ShortcutAndWidgetContainer{7f4ec4e V.E… … 0,0-1360,2104}
AppIcon {无人农机终端}
AppIcon {UTSmartCook}
com.android.quickstep.views.RecentsViewContainer{59c916f G.E… …I. 0,0-0,0 #7f0900de app:id/overview_panel_container}
com.android.quickstep.views.LauncherRecentsView{2d3ee7c V.ED… …ID 0,0-0,0 #7f0900dd app:id/overview_panel}
com.android.quickstep.views.ClearAllButton{6ce8305 VFED…C… …I. 0,0-0,0 #7f09003c app:id/clear_all_button}
android.widget.FrameLayout{cb77f5a V.E… …I. 0,0-0,0 #7f0900dc app:id/overview_guide_ani_view}
android.widget.LinearLayout{c8ad58b V.E… …I. 0,0-0,0 #7f0900df app:id/overview_swipeup_arrow}
android.view.View{8af7668 I.ED… …I. 0,0-0,0 #7f0900e0 app:id/overview_swipeup_guide_arrow1}
android.view.View{5394a81 I.ED… …I. 0,0-0,0 #7f0900e1 app:id/overview_swipeup_guide_arrow2}
com.android.launcher3.SwipeUpGuideText{ede3726 I.ED… …I. 0,0-0,0 #7f0900e2 app:id/overview_swipeup_guide_text}
com.android.launcher3.Hotseat{6cf3f67 V.E… … 0,2436-1440,2712 #7f090087 app:id/hotseat}
com.android.launcher3.CellLayout{3e3627b V.ED…L. … 0,0-1440,276 #7f0900a7 app:id/layout}
android.widget.LinearLayout{c399114 V.E… … 0,0-0,0}
android.widget.ImageButton{82f0dbd VFED…C… …I. 0,0-0,0}
com.android.launcher3.ClickShadowView{f669fb2 V.ED… … 40,0-428,324}
com.android.launcher3.ShortcutAndWidgetContainer{9066b03 V.E… … 40,0-1480,276}
AppIcon {手机}
AppIcon {信息}
AppIcon {照相机}
AppIcon {图片库}
android.widget.Button{3a8aa80 GFED…C… …I. 0,0-0,0 #7f09004e app:id/default_screen}
com.lge.launcher3.OverViewPanel{447b0ac I.E… … 0,2248-1440,2712 #7f0900af app:id/lg_overview_panel}
android.widget.FrameLayout{1c3c8b9 V.E… … 0,0-360,464}
android.widget.TextView{f9b04fe VFED…C… … 30,0-330,273 #7f090147 app:id/widget_button}
android.widget.FrameLayout{afab45f G.E… …I. 0,0-0,0}
android.widget.TextView{2deeac VFED…C… …ID 0,0-0,0 #7f090141 app:id/wallpaper_button}
android.widget.FrameLayout{74f3775 V.E… … 360,0-720,464}
android.widget.TextView{91e730a VFED…C… … 30,0-330,273 #7f090136 app:id/theme_button}
android.widget.FrameLayout{cc0377b G.E… …I. 0,0-0,0}
android.widget.TextView{2e14998 VFED… …ID 0,0-0,0 #7f090116 app:id/settings_button_vzw}
android.widget.FrameLayout{1e8d5f1 G.E… …I. 0,0-0,0}
android.widget.TextView{ab8b5d6 VFED… …ID 0,0-0,0 #7f09005b app:id/dynamic_gird_button}
android.widget.FrameLayout{190d057 V.E… … 720,0-1080,464}
android.widget.TextView{46d6744 VFED…C… … 30,0-330,273 #7f090115 app:id/settings_button}
android.widget.FrameLayout{aa3e02d V.E… … 1080,0-1440,464}
android.widget.TextView{5e25962 VFED…C… … 30,0-330,326 #7f0900f1 app:id/recent_uninstall_button}
com.lge.launcher3.dynamicgrid.DynamicGridPannelView{c681af3 G.E… …I. 0,0-0,0 #7f0900d9 app:id/overview_dynamic_panel}
android.widget.LinearLayout{b7bb3b0 V.E… …I. 0,0-0,0}
android.widget.LinearLayout{e8b5229 VFE…C… …I. 0,0-0,0 #7f0900d5 app:id/overview_dynaic_grid_layout1}
android.widget.ImageView{910a9ae V.ED… …I. 0,0-0,0 #7f0900d1 app:id/overview_dynaic_grid_icon1}
android.widget.TextView{a5f734f V.ED… …ID 0,0-0,0 #7f0900e3 app:id/overview_text1}
android.widget.LinearLayout{de05adc VFE…C… …I. 0,0-0,0 #7f0900d6 app:id/overview_dynaic_grid_layout2}
android.widget.ImageView{65de7e5 V.ED… …I. 0,0-0,0 #7f0900d2 app:id/overview_dynaic_grid_icon2}
android.widget.TextView{2c1b2ba V.ED… …ID 0,0-0,0 #7f0900e4 app:id/overview_text2}
android.widget.LinearLayout{6c9f56b VFE…C… …I. 0,0-0,0 #7f0900d7 app:id/overview_dynaic_grid_layout3}
android.widget.ImageView{88648c8 V.ED… …I. 0,0-0,0 #7f0900d3 app:id/overview_dynaic_grid_icon3}
android.widget.TextView{e0a1d61 V.ED… …ID 0,0-0,0 #7f0900e5 app:id/overview_text3}
android.widget.LinearLayout{9484086 VFE…C… …I. 0,0-0,0 #7f0900d8 app:id/overview_dynaic_grid_layout4}
android.widget.ImageView{5107d47 V.ED… …I. 0,0-0,0 #7f0900d4 app:id/overview_dynaic_grid_icon4}
android.widget.TextView{a1b2974 V.ED… …ID 0,0-0,0 #7f0900e6 app:id/overview_text4}
android.widget.LinearLayout{7ea2e9d V.E… …I. 0,0-0,0}
android.widget.Button{357df12 VFED…C… …I. 0,0-0,0 #7f0900db app:id/overview_dynamicgrid_cancel_btn}
android.widget.Button{c4da6e3 VFED…C… …I. 0,0-0,0 #7f0900da app:id/overview_dynamicgrid_apply_btn}
com.lge.launcher3.pageindicator.PageIndicatorExtension{e89fc50 V.E… … 606,2280-834,2436 #7f0900e7 app:id/page_indicator}
com.lge.launcher3.pageindicator.PageIndicatorMarkerExtension{413b6b2 VFE…CL. … 0,40-76,116}
android.widget.ImageView{c7b68e0 V.ED… … 20,20-56,56 #7f090091 app:id/inactive}
android.widget.ImageView{7c01799 V.ED… … 20,20-56,56 #7f090013 app:id/active}
com.lge.launcher3.pageindicator.PageIndicatorMarkerExtension{dbb3603 VFE…CL. … 76,40-152,116}
android.widget.ImageView{d50da5e V.ED… … 20,20-56,56 #7f090091 app:id/inactive}
android.widget.ImageView{a9ce3f V.ED… … 20,20-56,56 #7f090013 app:id/active}
com.lge.launcher3.pageindicator.PageIndicatorMarkerExtension{8090bb9 VFE…CL. … 152,40-228,116}
android.widget.ImageView{8de330c V.ED… … 20,20-56,56 #7f090091 app:id/inactive}
android.widget.ImageView{1719455 V.ED… … 20,20-56,56 #7f090013 app:id/active}
android.widget.LinearLayout{74c3e6a V.E… … 654,2272-786,2436 #7f090126 app:id/swipeup_arrow}
android.view.View{6770f5b I.ED… …I. 0,0-132,132 #7f090127 app:id/swipeup_guide_arrow1}
android.view.View{2c173f8 I.ED… …I. 0,32-132,164 #7f090128 app:id/swipeup_guide_arrow2}
com.android.launcher3.SwipeUpGuideText{78420d1 I.ED… …I. 0,2264-1440,2436 #7f090129 app:id/swipeup_guide_text}
com.lge.launcher3.droptarget.LGSearchDropTargetBar{7e7d736 I.E… …ID 0,136-1440,345 #7f09010c app:id/search_drop_target_bar}
android.widget.FrameLayout{b0d4637 V.E… …ID 0,0-1440,209 #7f090057 app:id/drag_target_bar}
android.widget.FrameLayout{595d7a4 G.E… …ID 0,0-1440,209}
com.android.launcher3.DeleteDropTarget{558f90d V.ED… …ID 0,0-1440,209 #7f09004f app:id/delete_target_text}
android.widget.FrameLayout{fd230c2 V.E… …ID 0,0-1440,209}
com.lge.launcher3.droptarget.LGUninstallDropTarget{5e8305c V.ED… …ID 0,0-1440,209 #7f09013d app:id/uninstall_target_text}
android.widget.FrameLayout{f660ed3 G.E… …ID 0,0-1440,209}
com.lge.launcher3.droptarget.CancelDropTarget{12aca10 V.ED… …ID 0,0-1440,209 #7f090034 app:id/cancel_target_text}
android.widget.FrameLayout{1291909 G.E… …ID 0,0-1440,209}
com.lge.launcher3.droptarget.DisableDropTarget{a16970e V.ED… …ID 0,0-1440,209 #7f090050 app:id/disable_target_text}
android.widget.LinearLayout{78c52f V.E… … 0,0-1440,209}
com.lge.launcher3.droptarget.LGUninstallDropTarget{da773c G.ED… …ID 0,0-0,0 #7f09001f app:id/all_apps_uninstall_target_text}
com.lge.launcher3.droptarget.DisableDropTarget{1c13cc5 G.ED… …ID 0,0-0,0 #7f09001a app:id/all_apps_disable_target_text}
com.android.launcher3.DeleteDropTarget{529161a G.ED… …ID 0,0-0,0 #7f090019 app:id/all_apps_delete_target_text}
android.widget.TextView{956854b G.ED… …I. 0,0-544,184}
android.widget.TextView{975cb28 G.ED… …I. 0,0-544,184}
android.widget.TextView{3fde041 G.ED… …I. 0,0-544,184}
android.widget.TextView{b279e6 G.ED… …I. 0,0-544,184}
com.lge.launcher3.widgettray.LGWidgetContainerView{6f7ec34 GFE… …ID 0,96-1440,2712 #7f090161 app:id/widgets_view}
android.widget.LinearLayout{baf9307 V.E… …ID 0,0-1440,2616 #7f090149 app:id/widget_container}
android.widget.FrameLayout{b062b27 V.E… …ID 0,0-1440,176}
com.lge.launcher3.allapps.AllAppsSearch{9f071d4 G.E… …I. 0,0-0,0 #7f090155 app:id/widget_search_bar}
android.widget.ImageView{c073f7d VFED…C… …I. 0,0-0,0 #7f09001e app:id/all_apps_search_exit}
android.widget.SearchView{c1c4e72 VFE… …I. 0,0-0,0 #7f09001d app:id/all_apps_search_edittext}
android.widget.LinearLayout{62052c3 V.E… …I. 0,0-0,0 #10203d1 android:id/search_bar}
android.widget.TextView{accd740 G.ED… …I. 0,0-0,0 #10203d0 android:id/search_badge}
android.widget.ImageView{e4d5679 GFED…C… …I. 0,0-0,0 #10203d2 android:id/search_button}
android.widget.LinearLayout{1dcdfbe V.E… …I. 0,0-0,0 #10203d4 android:id/search_edit_frame}
android.widget.ImageView{22b581f G.ED… …I. 0,0-0,0 #10203d6 android:id/search_mag_icon}
android.widget.LinearLayout{848276c V.E… …I. 0,0-0,0 #10203d7 android:id/search_plate}
android.widget.SearchViewKaTeX parse error: Expected ‘}’, got ‘#’ at position 55: …….ID 0,0-0,0 #̲10203d8 android…SearchAutoComplete{4c9f2b1 VFED…CL. …ID 0,0-0,0 #10203d8 android:id/search_src_text}
android.widget.ImageView{7d47396 GFED…C… …I. 0,0-0,0 #10203d3 android:id/search_close_btn}
android.widget.LinearLayout{cb11b17 G.E… …I. 0,0-0,0 #1020434 android:id/submit_area}
android.widget.ImageView{873bb04 GFED…C… …I. 0,0-0,0 #10203d5 android:id/search_go_btn}
android.widget.ImageView{55a08ed GFED…C… …I. 0,0-0,0 #10203da android:id/search_voice_btn}
android.widget.ImageView{a5c3322 G.ED… …I. 0,0-0,0 #7f09002c app:id/blur_background_in_top_of_draglayer}
android.view.ViewStub{f2251b3 G.E… …I. 0,0-0,0 #7f0900a6 app:id/launcher_overlay_stub}
Looper (main, tid 2) {9f38370}
Message 0: { when=+3s125ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 1: { when=+14s461ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 2: { when=+14s525ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 3: { when=+14s743ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 4: { when=+14s896ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 5: { when=+40s43ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 6: { when=+40s43ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 7: { when=+57s234ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
Message 8: { when=+57s788ms what=2 target=com.lge.launcher3.liveicon.LiveIcon$1 }
(Total messages: 9, polling=false, quitting=false)
AutofillManager:
sessionId: -2147483648
state: UNKNOWN
context: com.lge.launcher3.LauncherExtension@11b312f
client: com.lge.launcher3.LauncherExtension@11b312f (android.os.BinderProxy@a1d820)
enabled: false
hasService: true
hasCallback: false
onInvisibleCalled false
last autofilled data: null
tracked views: null
fillable ids: null
entered ids: null
save trigger id: null
save on finish(): false
compat mode enabled: false
debug: false verbose: false
Autofill Compat Mode: false
ResourcesManager:
cached apks: 0 [cache disabled]
total apks: 3
resources: 4
resource impls: 3

4、卸载你想卸载的应用

上一步中我们拿到了你想要的卸载应用的包名了,这一步就小儿科了!
提供下面命令:

卸载: adb shell pm uninstall –user 0 应用包名
停用: adb shell pm disable-user 应用包名
启用: adb shell pm enable 应用包名

参考:
【1】、adb命令查看当前运行activity
【2】、android 开发中Adb命令的使用查看所有的Apk包

Linux怎样创建FTP服务器–修改用户默认目录-完美解决

  1.  
  2. 在创建FTP服务器之有先命令: ps -ef |grep vsftpd查一下系统有没有安装vsftpd这个服务器,如果出现如下图所示的界面说明没有安装。
  3.  然后再执行:yum install vsftpd -y进行在线安装vsftpd这个服务。
  4.  安装成功以后需要把匿名登陆的这个功能关闭了。使用命令: vim /etc/vsftpd/vsftpd.conf然后在里成找到:‍ anonymous_enable=NO
  5.  然后再查看一下vsftpd这个服务有没有启动。使用命令: chkconfig –list如果你如下图所示一样没有启动。没有启动使用启动:chkconfig –level 35 vsftpd on     
  6. 1、环境:ftp为vsftp。被限制用户名为test。被限制路径为/home/test2、建用户:在root用户下:useradd -d /home/test test //增加用户test,并制定test用户的主目录为/home/test   如果目录已经存在,会有提示,但是不影响用户的权限登陆
    passwd test //为test设置密码3、更改用户相应的权限设置:usermod -s /sbin/nologin test //限定用户test不能telnet,只能ftp
           usermod -s /sbin/bash test //用户test恢复正常
           usermod -d /test test //更改用户test的主目录为/test

    4、限制用户只能访问/home/test,不能访问其他路径修改/etc/vsftpd/vsftpd.conf如下:chroot_list_enable=YES //限制访问自身目录
    # (default follows)
    chroot_list_file=/etc/vsftpd/vsftpd.chroot_list编辑 vsftpd.chroot_list文件,将受限制的用户添加进去,每个用户名一行改完配置文件,不要忘记重启vsFTPd服务器
    [root@linuxsir001 root]# /etc/init.d/vsftpd restart5、如果需要允许用户修改密码,但是又没有telnet登录系统的权限:usermod -s /usr/bin/passwd test //用户telnet后将直接进入改密界面  
  7. 最后重启一下服务:service vsftpd start如果出现启动失败则可以使用:/etc/rc.d/init.d/vsftpd restart
  8.  成功链接FTP服务器上。    ————————————————————————————————–Linux下如何修改用户默认目录配置:
    1. 1、切换到root用户,直接修改/etc/passwd文件,找到你的用户名你一行,如下图所示修改路径,然后保存即可。
    2. 22、切换到root用户,使用usermod命令,例如usermod -d /tmp test (test为你的用户名),使用该命令请确保该用户下没有运行的软件或进程
    3. 3最后切换到普通账户,就会看到当前默认目录已经更改了。
    4.  
     如果用户不能上传文件,记得chmod -R 777 /file

Linux文件传输FTP详解

ftp命令用来设置文件系统相关功能。ftp服务器在网上较为常见,Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件,这里详细介绍Linux ftp命令的一些经常使用的命令,相信掌握了这些使用Linux进行ftp操作将会非常容易。

语法

ftp(选项)(参数)

选项

-d:详细显示指令执行过程,便于排错或分析程序执行的情况;
-i:关闭互动模式,不询问任何问题;
-g:关闭本地主机文件名称支持特殊字符的扩充特性;
-n:不使用自动登录;
-v:显示指令执行过程。

参数

主机:指定要连接的FTP服务器的主机名或ip地址。

实例

复制代码
FTP>ascii: 设定以ASCII方式传送文件(缺省值)
FTP>bell: 每完成一次文件传送,报警提示.
FTP>binary: 设定以二进制方式传送文件.
FTP>bye: 终止主机FTP进程,并退出FTP管理方式.
FTP>case: 当为ON时,用MGET命令拷贝的文件名到本地机器中,全部转换为小写字母.
FTP>cd: 同UNIX的CD命令.
FTP>cdup: 返回上一级目录.
FTP>chmod: 改变远端主机的文件权限.
FTP>close: 终止远端的FTP进程,返回到FTP命令状态, 所有的宏定义都被删除.
FTP>delete: 删除远端主机中的文件.
FTP>dir [remote-directory] [local-file] 列出当前远端主机目录中的文件.如果有本地文件,就将结果写至本地文件.
FTP>get [remote-file] [local-file] 从远端主机中传送至本地主机中.
FTP>help [command] 输出命令的解释.
FTP>lcd: 改变当前本地主机的工作目录,如果缺省,就转到当前用户的HOME目录.
FTP>ls [remote-directory] [local-file] 同DIR.
FTP>macdef: 定义宏命令.
FTP>mdelete [remote-files] 删除一批文件.
FTP>mget [remote-files] 从远端主机接收一批文件至本地主机.
FTP>mkdir directory-name 在远端主机中建立目录.
FTP>mput local-files 将本地主机中一批文件传送至远端主机.
FTP>open host [port] 重新建立一个新的连接.
FTP>prompt: 交互提示模式.
FTP>put local-file [remote-file] 将本地一个文件传送至远端主机中.
FTP>pwd: 列出当前远端主机目录.
FTP>quit: 同BYE.
FTP>recv remote-file [local-file] 同GET.
FTP>rename [from] [to] 改变远端主机中的文件名.
FTP>rmdir directory-name 删除远端主机中的目录.
FTP>send local-file [remote-file] 同PUT.
FTP>status: 显示当前FTP的状态.
FTP>system: 显示远端主机系统类型.
FTP>user user-name [password] [account] 重新以别的用户名登录远端主机.
FTP>? [command]: 同HELP. [command]指定需要帮助的命令名称。如果没有指定 command,ftp 将显示全部命令的列表。
FTP>! 从 ftp 子系统退出到外壳。
复制代码

详解:1. 连接ftp服务器

格式:ftp [hostname| ip-address]
a)在linux命令行下输入:ftp 192.168.1.1

b)服务器询问你用户名和密码,分别输入用户名和相应密码,待认证通过即可。

2. 下载文件

下载文件通常用get和mget这两条命令。
a) get 
格式:get [remote-file] [local-file]
将文件从远端主机中传送至本地主机中。
如要获取远程服务器上/usr/your/1.htm,则ftp> get /usr/your/1.htm 1.htm (回车)


b) mget      
格式:mget [remote-files]
从远端主机接收一批文件至本地主机。
如要获取服务器上/usr/your/下的所有文件,则ftp> cd /usr/your/
ftp> mget *.* (回车)


此时每下载一个文件,都会有提示。如果要除掉提示,则在mget *.* 命令前先执行:prompt off

注意:文件都下载到了linux主机的当前目录下。比如,在 /usr/my下运行的ftp命令,则文件都下载到了/usr/my下。

3.上传文件

a) put
格式:put local-file [remote-file]
将本地一个文件传送至远端主机中。
如要把本地的1.htm传送到远端主机/usr/your,并改名为2.htmftp> put 1.htm /usr/your/2.htm (回车)


b) mput
格式:mput local-files
将本地主机中一批文件传送至远端主机。
如要把本地当前目录下所有html文件上传到服务器/usr/your/ 下ftp> cd /usr/your (回车)
ftp> mput *.htm (回车)


注意:上传文件都来自于主机的当前目录下。比如,在 /usr/my下运行的ftp命令,则只有在/usr/my下的文件linux才会上传到服务器/usr/your 下。

4. 断开连接
bye:中断与服务器的连接。ftp> bye (回车) 

 命令介绍:

复制代码

1.FTP> ! 从 ftp子系统退出到外壳。
2.FTP> ? 显示 ftp命令说明。? 与 help相同。
  格式:? [command]
  说明:[command]指定需要帮助的命令名称。如果没有指定 command,ftp将显示全部命令的列表。
3.FTP> append 使用当前文件类型设置将本地文件附加到远程计算机上的文件。
  格式:append local-file [remote-file]
  说明:local-file 指定要添加的本地文件。
  remote-file 指定要添加 local-file的远程计算机上的文件。如果省略了 remote-file,本地文件名将被用作远程文件名。
4.FTP> ascii 将文件传送类型设置为默认的 ASCII。
  说明:FTP 支持两种文件传送类型,ASCII码和二进制图像。在传送文本文件时应该使用ASCII。
5.FTP> bell 切换响铃以在每个文件传送命令完成后响铃。默认情况下,铃声是关闭的。
6.FTP> binary(或bi)将文件传送类型设置为二进制。
7.FTP> bye(或by)结束与远程计算机的 FTP会话并退出 ftp。
8.FTP> cd 更改远程计算机上的工作目录。
  格式:cd remote-directory
  说明:remote-directory 指定要更改的远程计算机上的目录。
9.FTP> close 结束与远程服务器的 FTP会话并返回命令解释程序。
  FTP> debug 切换调试。当调试打开时,发送到远程计算机的每个命令都打印,前面是字符串“>”。默认情况下,调试是关闭的。
10.FTP> delete 删除远程计算机上的文件。
  格式:delete remote-file
  说明:remote-file 指定要删除的文件。
11.FTP> dir 显示远程目录文件和子目录列表。
  格式:dir [remote-directory] [local-file]
  说明:remote-directory 指定要查看其列表的目录。如果没有指定目录,将使用远程计算机中的当前工作目录。Local-file指定要存储列表的本地文件。如果没有指定,输出将显示在屏幕上。
12.FTP> disconnect从远程计算机断开,保留 ftp 提示。
13.FTP> get 使用当前文件转换类型将远程文件复制到本地计算机。
  格式:get remote-file [local-file]
  说明:remote-file 指定要复制的远程文件。
  Local-file 指定要在本地计算机上使用的名称。如果没有指定,文件将命名为 remote-file。
14.FTP >glob 切换文件名组合。组合允许在内部文件或路径名中使用通配符(*和?)。默认情况下,组合是打开的。
15.FTP >hash切换已传输的每个数据块的数字签名 (#) 打印。数据块的大小是2048字节。默认情况下,散列符号打印是关闭的。
16.FTP >help显示 ftp 命令说明。
  格式:help [command]
  说明:command 指定需要有关说明的命令的名称。如果没有指定 command,ftp将显示全部命令的列表。
17.FTP >lcd 更改本地计算机上的工作目录。默认情况下,工作目录是启动 ftp的目录。
  格式:lcd [directory]
  说明:directory 指定要更改的本地计算机上的目录。如果没有指定directory,将显示本地计算机中当前的工作目录。
18.FTP >literal 将参数逐字发送到远程 FTP服务器。将返回单个的 FTP 回复代码。
  格式:literal argument [ …]
  说明:argument 指定要发送到 FTP服务器的参数。
19.FTP >ls 显示远程目录文件和子目录的缩写列表。
  格式:ls [remote-directory] [local-file]
  说明:remote-directory 指定要查看其列表的目录。如果没有指定目录,将使用远程计算机中的当前工作目录。 local-file指定要存储列表的本地文件。如果没有指定,输出将显示在屏幕上。
20.FTP >mdelete 删除远程计算机上的文件。
  格式:mdelete remote-files [ …]
  说明:remote-files 指定要删除的远程文件。
21.FTP >mdir显示远程目录文件和子目录列表。可以使用 mdir 指定多个文件。
  格式:mdir remote-files [ …] local-file
  说明:remote-files 指定要查看列表的目录。必须指定 remote-files。请键入 -使用远程计算机上的当前工作目录。
  local-file 指定要还原列表的本地文件。请键入-在屏幕上显示列表。
22.FTP >mget 使用当前文件传送类型将远程文件复制到本地计算机。
  格式:mget remote-files [ …]
  说明:remote-files 指定要复制到本地计算机的远程文件。
23.FTP >mkdir 创建远程目录。
  格式:mkdir directory
  说明:directory 指定新的远程目录的名称。
24.FTP >mls 显示远程目录文件和子目录的缩写列表。
  格式:mls remote-files [ …] local-file
  说明:remote-files 指定要查看列表的文件。必须指定 remote-files;
  请键入- 使用远程计算机上的当前工作目录。
  local-file 指定要存储列表的本地文件。请键入 -以在屏幕上显示列表。
25.FTP >mput 使用当前文件传送类型将本地文件复制到远程计算机上。
  格式:mput local-files [ …]
  说明:local-files 指定要复制到远程计算机的本地文件
26.FTP >open 与指定的 FTP服务器连接。
  格式:open computer [port]
  说明:computer 指定要连接的远程计算机。可以通过 IP地址或计算机名称指定计算机(DNS 或主机文件必须可用)。如果自动登录打开(默认),ftp还将尝试自动将用户登录到 FTP 服务器port指定用来联系 FTP 服务器的端口号。
27.FTP >prompt 切换提示。如果关闭提示时 mget及 mput 传送所有文件,Ftp在多文件传送过程中将提示允许您有选择地检索或存储文件。默认情况下,提示是
  打开的。
28.FTP >put 使用当前文件传送类型将本地文件复制到远程计算机上。
  格式:put local-file [remote-file]
  说明:local-file 指定要复制的本地文件。
  remote-file 指定要在远程计算机上使用的名称。如果没有指定,文件将命名为 local-file。
29.FTP >pwd 显示远程计算机上的当前目录。
30.FTP >quit 结束与远程计算机的 FTP 会话并退出 ftp。
31.FTP >quote 将参数逐字发送到远程 FTP服务器。将返回单个的 FTP 回复代码。
  Quote 与 literal相同。
  格式:quote argument [ …]
  说明:argument 指定要发送到 FTP服务器的参数。
32.FTP >recv使用当前文件传送类型将远程文件复制到本地计算机。Recv 与 get相同。
  格式:recv remote-file [local-file]
  说明:remote-file 指定要复制的远程文件。
  local-file 指定要在本地计算机上使用的名称。如果没有指定,文件将命名为 remote-file。
33.FTP >remotehelp显示远程命令帮助。
  格式:remotehelp [command]
  说明:command 指定需要帮助的命令的名称。如果没有指定 command,ftp将显示全部远程命令的列表。
34.FTP >rename重命名远程文件。
  格式:rename filename newfilename
  说明:filename 指定要重命名的文件。 newfilename指定新的文件名。
35.FTP >rmdir 删除远程目录。
  格式:rmdir directory
  说明:directory 指定要删除的远程目录的名称。
36.FTP >send 使用当前文件传送类型将本地文件复制到远程计算机上。Send与put 相同。
  格式:send local-file [remote-file]
  说明:local-file 指定要复制的本地文件。 remote-file指定要在远程计算机上使用的名称。如果没有指定,文件将命名为 local-file。
37.FTP >status 显示 FTP 连接和切换的当前状态。
38.FTP >trace 切换数据包跟踪。Trace在运行 ftp 命令时显示每个数据包的路由。
39.FTP >type 设置或显示文件传送类型。
  格式:type [type-name]
  说明:type-name 指定文件传送类型。默认设置为 ascii。如果没有指定type-name,将显示当前的类型。
40.FTP >user 指定远程计算机的用户。
  格式:user username [password] [account]
  说明:user-name 指定登录到远程计算机所使用的用户名。password指定 user-name 的密码。如果没有指定,但必须指定,ftp会提示输入密码。
  account 指定登录到远程计算机所使用的帐户。如果没有指定account,但是需要指定,ftp会提示您输入帐户。
41.FTP >verbose 切换 verbose模式。如果打开,将显示所有 ftp 响应。在文件传送完成后,将同时显示与传送效率有关的统计信息。默认情况下,verbose是打开的。

复制代码

附录:ftp命令表

FTP采用客户端/服务器模型,客户端和服务器使用TCP建立连接。在服务器端,FTP有两个预分配的的端口号,分别为20和21.其中,端口20用于发送和接受FTP数据(ASCII码或二进制文件),该数据端口只在传输数据是打开,并在传输结束时关闭。端口21用于发送和接受FTP的控制信息,FTP服务器通过侦听这个端口来判断是否有ftp客户端的连接请求,FTP会话建立后,端口21的连接在会话期间始终保持打开状态。

在客户端,当发出请求时动态分配端口号,选择范围为1024~65535.当一个FTP会话开始后,客户端程序打开一个控制端口(如1038),该端连接到服务器上的21端口,接受和发送控制信命令;需要传输数据时,客户端再打开第二个端口(如1039),连接到服务器上的20端口。每当开始传输文件时,客户端程序会打开一个新的数据端口,在文件传输完毕后,再自动释放该端口。

该命令的语法格式如下所示:

ftp [-v] [-d] [–i] [-n] [-g] [-k realm] [-x] [-u] [host]

复制代码
ftp命令主要选项说明

 选项  说明
 -d     启动调试模式
 -u     关闭自动认证
 -e     不记录历史指令
 -i     关闭交互模式
 -x     在成功认证之后,协商密钥
 -n     关闭自动登录功能
 -p     传输文件模式为被动模式
 -v     程序运行时,显示详细的处理信息
 -k realm     使用Kerberos v4认证时,从realm中得到信息
 host     FTP服务器的主机名/IP地址
复制代码

在客户端访问FTP时,如果没有在命令行给出服务器的主机名或IP,则客户端将出现“ftp>”提示符,等待用户输入ftp内部命令
常见ftp内部命令及其说明

 内部命令  说明

复制代码
ls     显示服务器上的目录
get     从服务器下载指定文件到客户端
put     从客户端传送指定文件到服务器
open     连接ftp服务器
quit     断开连接并退出ftp服务器
cd directory     改变服务器的当前目录为directory
lcd directory     改变本地的当前目录为directory
bye     退出ftp命令状态
ascii     设置文件传输方式为ASCII模式
binary     设置文件传输方式为二进制模式
!     执行本地主机命令
cd     切换远端ftp服务器上的目录
cdup     上一层目录
close     在不结束ftp进程的情况下,关闭与ftp服务器的连接
delete     删除远端ftp服务器上的文件
get     下载
hash     显示#表示下载进度
mdelete     删除文件,模糊匹配
mget     下载文件,模糊匹配
mput     上传文件,模糊匹配
mkdir     在远端ftp服务器上,建立文件夹
newer     下载时,检测是不是新文件
prompt     关闭交互模式
put     上传
pwd     显示当前目录
复制代码

ftp使用的内部命令如下(中括号表示可选项):

复制代码
1.![cmd[args]]:在本地机中执行交互shell,exit回到ftp环境,如:!ls*.zip.
2.$ macro-ame[args]:执行宏定义macro-name.
3.account[password]:提供登录远程系统成功后访问系统资源所需的补充口令。
4.append local-file[remote-file]:将本地文件追加到远程系统主机,若未指定远程系统文件名,则使用本地文件名。
5.ascii:使用ascii类型传输方式。
6.bell:每个命令执行完毕后计算机响铃一次。
7.bin:使用二进制文件传输方式。
8.bye:退出ftp会话过程。
9.case:在使用mget时,将远程主机文件名中的大写转为小写字母。
10.cd remote-dir:进入远程主机目录。
11.cdup:进入远程主机目录的父目录。
12.chmod mode file-name:将远程主机文件file-name的存取方式设置为mode,如:chmod 777 a.out。
13.close:中断与远程服务器的ftp会话(与open对应)。
14.cr:使用asscii方式传输文件时,将回车换行转换为回行。
15.delete remote-file:删除远程主机文件。
16.debug[debug-value]:设置调试方式,显示发送至远程主机的每条命令,如:deb up 3,若设为0,表示取消debug。
17.dir[remote-dir][local-file]:显示远程主机目录,并将结果存入本地文件local-file。
18.disconnection:同close。
19.form format:将文件传输方式设置为format,缺省为file方式。
20.get remote-file[local-file]:将远程主机的文件remote-file传至本地硬盘的local-file。
21.glob:设置mdelete,mget,mput的文件名扩展,缺省时不扩展文件名,同命令行的-g参数。
22.hash:每传输1024字节,显示一个hash符号(#)。
23.help[cmd]:显示ftp内部命令cmd的帮助信息,如:help get。
24.idle[seconds]:将远程服务器的休眠计时器设为[seconds]秒。
25.image:设置二进制传输方式(同binary)。
26.lcd[dir]:将本地工作目录切换至dir。
27.ls[remote-dir][local-file]:显示远程目录remote-dir,并存入本地文件local-file。
28.macdef macro-name:定义一个宏,遇到macdef下的空行时,宏定义结束。
29.mdelete[remote-file]:删除远程主机文件。
30.mdir remote-files local-file:与dir类似,但可指定多个远程文件,如:mdir *.o.*.zipoutfile
31.mget remote-files:传输多个远程文件。
32.mkdir dir-name:在远程主机中建一目录。
33.mls remote-file local-file:同nlist,但可指定多个文件名。
34.mode[modename]:将文件传输方式设置为modename,缺省为stream方式。
35.modtime file-name:显示远程主机文件的最后修改时间。
36.mput local-file:将多个文件传输至远程主机。
37.newer file-name:如果远程机中file-name的修改时间比本地硬盘同名文件的时间更近,则重传该文件。
38.nlist[remote-dir][local-file]:显示远程主机目录的文件清单,并存入本地硬盘的local-file。
39.nmap[inpattern outpattern]:设置文件名映射机制,使得文件传输时,文件中的某些字符相互转换,如:nmap $1.$2.$3[$1,$2].[$2,$3],则传输文件a1.a2.a3时,文件名变为a1,a2。该命令特别适用于远程主机为非UNIX机的情况。
40.ntrans[inchars[outchars]]:设置文件名字符的翻译机制,如ntrans 1R,则文件名LLL将变为RRR。
41.open host[port]:建立指定ftp服务器连接,可指定连接端口。
42.passive:进入被动传输方式。
43.prompt:设置多个文件传输时的交互提示。
44.proxy ftp-cmd:在次要控制连接中,执行一条ftp命令,该命令允许连接两个ftp服务器,以在两个服务器间传输文件。第一条ftp命令必须为open,以首先建立两个服务器间的连接。
45.put local-file[remote-file]:将本地文件local-file传送至远程主机。
46.pwd:显示远程主机的当前工作目录。
47.quit:同bye,退出ftp会话。
48.quote arg1,arg2…:将参数逐字发至远程ftp服务器,如:quote syst.
49.recv remote-file[local-file]:同get。
50.reget remote-file[local-file]:类似于get,但若local-file存在,则从上次传输中断处续传。
51.rhelp[cmd-name]:请求获得远程主机的帮助。
52.rstatus[file-name]:若未指定文件名,则显示远程主机的状态,否则显示文件状态。
53.rename[from][to]:更改远程主机文件名。
54.reset:清除回答队列。
55.restart marker:从指定的标志marker处,重新开始get或put,如:restart 130。
56.rmdir dir-name:删除远程主机目录。
57.runique:设置文件名唯一性存储,若文件存在,则在原文件后加后缀..1,.2等。
58.send local-file[remote-file]:同put。
59.sendport:设置PORT命令的使用。
60.site arg1,arg2…:将参数作为SITE命令逐字发送至远程ftp主机。
61.size file-name:显示远程主机文件大小,如:site idle 7200。
62.status:显示当前ftp状态。
63.struct[struct-name]:将文件传输结构设置为struct-name,缺省时使用stream结构。
64.sunique:将远程主机文件名存储设置为唯一(与runique对应)。
65.system:显示远程主机的操作系统类型。
66.tenex:将文件传输类型设置为TENEX机的所需的类型。
67.tick:设置传输时的字节计数器。
68.trace:设置包跟踪。
69.type[type-name]:设置文件传输类型为type-name,缺省为ascii,如:type binary,设置二进制传输方式。
70.umask[newmask]:将远程服务器的缺省umask设置为newmask,如:umask 3。
71.user user-name[password][account]:向远程主机表明自己的身份,需要口令时,必须输入口令,如:user anonymous my@email。
72.verbose:同命令行的-v参数,即设置详尽报告方式,ftp服务器的所有响应都将显示给用户,缺省为on.
73.?[cmd]:同help。
复制代码

附表:

ascii为文本文件设置传输方式为ascii
bell命令完成时响铃
binary 设置传输方式为二进制,这是缺省设置
bye 终止ftp会话,并退出
cd dir_name切换远程主机上目录
cdup切换远程主机上目录至上一级目录
close终止到远程主机的ftp会话
delete file_name删除远程主机中的文件
dir 显示远程主机上目录列表
get file_name下载一个文件
hash 每传输一定数量数据打印`#’
lcd dir_name切换本地工作目录
ls 列表远程主机目录中的信息
mdelete file_names删除多个文件
mget file_names下载多个文件
mkdir dir_name在远程主机上创建目录
mput file_names上传多个文件
open site_name连接到远程tftp
prompt设置多个文件传输时的交互提示
put file_name上传一个文件
pwd显示远程主机当前工作目录
quit 终止ftp会话并退出
rename old_name new_name重命名文件
rmdir dir_name删除远程主机上的某个目录
size file_name显示远程主机上某个文件的大小
status 显示当前状态
system显示远程主机操作系统类型
tenex 将文件传输类型设置为tenex机所需的类型
user向远程主机发送用户信息(登录信息)
verbose 开关verbose方式,远程主机所有响应都显示给客户

 参考文章:https://blog.csdn.net/yexiangCSDN/article/details/80988355https://blog.csdn.net/sandy9919/article/details/81334064 作者:HuZixia出处:http://www.cnblogs.com/huzixia/本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。标签: FTP

linux 下 修改ftp上传文件目录

[root@localhost local]# chown ftp用户名 ftp上传的文件夹

[root@localhost local]# chgrp ftp用户名 ftp上传的文件夹

[root@localhost local]# chmod 755 ftp上传的文件夹

[root@localhost local]# ll |grep ftp上传的文件夹drwxr-xr-x  3 ftp用户  root 4096 Mar  7  2013 ftp上传的文件夹
[root@localhost local]# usermod -d ftp上传的全路径 ftp用户名查看“Directory”的值是否更改成功:[root@localhost local]# finger ftp用户名Login: ftp用户名                        Name: (null)Directory: 修改后的全路径     Shell: /sbin/nologinNever logged in.No mail.No Plan.

https://blog.csdn.net/lvhaidongbk/article/details/45690431

Linux中配置ftp传输

ftp的配置及使用

1.安装ftp:

  yum install -y vsftpd

出现如图所示,则表示安装成功

2.关闭防火墙:

  service iptables stop

3.创建一个用户用于ftp传输(或者使用已存在的)

  adduser hxc

4.设置密码

  passwd hxcftp  (回车再输入两遍密码)

5.切换到ftp的配置目录:

  cd /etc/vsftpd/

6.编辑该目录下的文件user_list :

  vim user_list

7.编辑里面的内容,将需要的用户添加进该文件夹中,这里增加hxc用户作为ftp使用,使用命令:cat user_list 查看是否添加成功

8.再编辑该目录下的配置文件:

  vim vsftpd.conf 

在该配置文件中增加userlist_deny=NO  后保存退出:

9.重启ftp服务:

  service vsftpd restart

10.在windows的命令窗口中输入命令:ftp 连接的IP地址  回车

如果不知道连接的地址,在Linux中输入:ifconfig  查看

11.然后输入用户名及密码,登陆即可

如果出现如下错误:500 OOPS: cannot change directory:/home/xxx 500 OOPS: child died

关于该问题的解决方案https://www.cnblogs.com/sun-flower1314/p/9574732.html

使用 ftp 传输文件至Linux服务器查看:https://www.cnblogs.com/sun-flower1314/p/11226339.html

谢谢!!

 希望各位给出宝贵意见,不甚感激!!

php通过strpos查找字符串出现位置的方法

这篇文章主要介绍了php通过strpos查找字符串出现位置的方法,实例分析了strpos的功能及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下

dubbo

本文实例讲述了php通过strpos查找字符串出现位置的方法。分享给大家供大家参考。具体分析如下:

strpos用来查找一个字符串在另一个字符串中首次出现的位置,strpos区分大小写,如果没有找到则返回false,所以strpos有两种类型的返回值,一种是整形,一种是bool型,开发过程中需要注意

123<?phpecho strpos("Hello world!","wo");?>

输出结果:6

由于strpos有两种类型的返回值,所以在判断是否找到子字符串的的时候最好使用===三个等号进行严格类型的相等比较

1234567891011121314<?php$haystack = "needle23423432";$pos = strpos($haystack, "needle");if ($pos==false) {print("Not found based (==) test\n");} else {print("Found based (==) test\n");}if ($pos===false) {print("Not found based (===) test\n");} else {print("Found based (===) test\n");}?>

上面的代码返回如下结果

123456This script will print: Not found based (==) testFound based (===) test The (===) test is correct.

希望本文所述对大家的php程序设计有所帮助。

有以下几种bai方法:

stripos() 返回字符串在另一字du符串zhi中第一次出现的位置(大小写不敏感dao)

stristr() 查找字符串在另一字符串中第一次出现的位置(大小写不敏感)

strpos() 返回字符串在另一字符串中首次出现的位置(对大小写敏感)

strrchr() 查找字符串在另一个字符串中最后一次出现的位置。

strripos() 查找字符串在另一字符串中最后出现的位置(对大小写不敏感)

strrpos() 查找字符串在另一字符串中最后出现的位置(对大小写敏感)

扩展资料:

PHP常用函数:

strtoupper()函数把字符串转换为大写

strtolower()函数把字符串转换为小写

strtok()函数把字符串分割为更小的字符串

strstr()函数搜索一个字符串在另一个字符串中的第一次出现

strspn()函数返回在字符串中包含的特定字符的数目

strrpos()函数查找字符串在另一个字符串中最后一次出现的位置

strripos()函数查找字符串在另一个字符串中最后一次出现的位置

js 实现分享功能(分享到qq空间,新浪微博)

//分享到新浪微博 function shareToXl(title,url,picurl){ var sharesinastring= ‘http://v.t.sina.com.cn/share/share.php?title=’+title+’&url=’+url+’&content=utf-8&sourceUrl=’+url+’&pic=’+picurl; window.open(sharesinastring,’newwindow’,’height=400,width=400,top=100,left=100′); }
//分享到qq空间 function shareToQq(title,url,picurl){ var shareqqzonestring= ‘http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?summary=’+title+’&url=’+url+’&pics=’+picurl; window.open(shareqqzonestring,’newwindow’,’height=400,width=400,top=100,left=100′); } function subinfo(){ shareToQq(“测试标题”,”www.baidu.com”,”http://aladdin-vray.oss-cn-beijing.aliyuncs.com/Other/80de988c-ad11-449b-af48-b5341c957668.jpg”); }
以上的函数分别具有三个参数,内容,网址,以及 图片,也就是我们想要分享的内容

聊天机器人的定义和现状

聊天机器人,是一种通过自然语言模拟人类进行对话的程序。通常运行在特定的软件平台上,如PC平台或者移动终端设备平台。

近年来,很多科技公司都开始推出基于聊天机器人的AI产品和技术,如微软在2016年Build开发者大会发布了BOT平台,在此之前还推出过基于情感计算的聊天机器人小冰;Facebook在2016年发布了Facebook Messenger bot开发者平台;百度也推出了用于交互式搜索的聊天机器人小度。聊天机器人系统可以看作是机器人产业与“互联网+”的结合,符合国家的科研及产业化发展方向。

 从应用场景的角度来看,聊天机器人可以分为在线客服、娱乐、教育、个人助理和智能问答五个种类。

 在线客服聊天机器人系统的主要功能是同用户进行基本沟通并自动回复用户有关产品或服务的问题,以实现降低企业客服运营成本、提升用户体验的目的。其应用场景通常为网站首页和手机终端。代表性的商用系统有小I机器人、京东的JIMI客服机器人等。用户可以通过与JIMI聊天了解商品的具体信息以及反馈购物中存在的问题等。值得称赞的是,JIMI具备一定的拒识能力,即能够知道自己不能回答用户的哪些问题以及何时应该转向人工客服。

娱乐场景下聊天机器人系统的主要功能是同用户进行开放主题的对话,从而实现对用户的精神陪伴、情感慰藉和心理疏导等作用。其应用场景通常为社交媒体、儿童玩具等。代表性的系统如微软“小冰”、微信“小微”、“小黄鸡”、“爱情玩偶”等。其中微软“小冰”和微信“小微”除了能够与用户进行开放主题的聊天之外,还能提供特定主题的服务,如天气预报和生活常识等。

应用于教育场景下的聊天机器人系统根据教育的内容不同包括构建交互式的语言使用环境,帮助用户学习某种语言;在学习某项专业技能中,指导用户逐步深入地学习并掌握该技能;在用户的特定年龄阶段,帮助用户进行某种知识的辅助学习等。其应用场景通常为具备人机交互功能的学习、培训类软件以及智能玩具等。这里以科大讯飞公司的开心熊宝(具备移动终端应用软件和实体型玩具两种形态)智能玩具为例,“熊宝”可以通过语音对话的形式辅助儿童学习唐诗、宋词以及回答简单的常识性问题等。

个人助理类应用主要通过语音或文字与聊天机器人系统进行交互,实现个人事务的查询及代办功能,如天气查询、空气质量查询、定位、短信收发、日程提醒、智能搜索等,从而更便捷地辅助用户的日常事务处理。其应用场景通常为便携式移动终端设备。代表性的商业系统有AppleSiri、GoogleNow、微软Cortana、出门问问等。

智能问答类的聊天机器人主要功能包括回答用户以自然语言形式提出的事实型问题和需要计算和逻辑推理型的问题,以达到直接满足用户的信息需求及辅助用户进行决策的目的。其应用场景通常作为问答服务整合到聊天机器人系统中。典型的智能问答系统除了IBMWatson之外,还有WolframAlpha和Magi,后两者都是基于结构化知识库的问答系统,且分别仅支持英文和中文的问答。

微信聊天机器人的技术架构

本文实现的的聊天机器人是基于微信公众号开发平台,微信用户订阅机器人公众号,然后就可以愉快的聊天了。

整个系统的数据流图如下:

接下来就是对业务架构进行技术实现选型。

需要我们自己实现的是上图中的Chatbot Server和Chatbot Engine。

Chatbot Server其实就是一个普通的微信开发者应用服务器,所有基于微信平台的应用开发都需要有自己的服务器。

Chatbot Engine是聊天机器人的具体实现,提供SDK或者Rest API接口给Chatbot Server调用。

对于Chatbot Server,github上有一些开源的微信应用开发框架,利用它们可以轻松实现一个微信应用服务器,本文采用(https://github.com/messense/wechat-bot)项目,它不仅包含了web server,还完整的实现了微信chatbot功能。

对于Chatbot Engine,github上也有一些开源的chatbot框架,基于这些框架,可以开发自己的聊天引擎,本文采用(https://github.com/gunthercox/ChatterBot)项目,它提供了一个chatbot框架,可以扩展自己的引擎适配器。

技术实现

Chatbot Server

本例采用https://github.com/messense/wechat-bot项目。

其web server采用tornado,并采用wechatpy(https://github.com/jxtech/wechatpy)作为微信开发SDK。

项目的bot引擎可扩展,目前支持 simsimi,talkbot,v2ex等引擎,这些都是商业引擎的。

我们自己编写插件,支持chatterbot引擎,只需要实现respond接口就可以了。

#coding=utf-8

from chatterbot import ChatBot

from chatterbot.trainers import ChatterBotCorpusTrainer

deepbot =  ChatBot(

    ‘yuntongxun’,

    logic_adapters=[

        “chatterbot.adapters.logic.ClosestMatchAdapter”,

#        “chatterbot.adapters.logic.DeepLogicAdapter”

    ]

)

deepbot.set_trainer(ChatterBotCorpusTrainer)

deepbot.train(“chatterbot.corpus.english”)

deepbot.train(“chatterbot.corpus.chinese”)

__name__ = ‘deepbot’

def test(data, msg=None, bot=None):

    return True

def respond(data, msg=None, bot=None):

    return str(deepbot.get_response(data))

if __name__ == ‘__main__’:

    print(respond(“你好”))

Chatbot Engine

Chatbot Server 调用Chatbot Engine有2种方式,一种是Chatbot Engine以SDK的方式提供给Chatbot Server本地调用,一种是将Chatbot Engine封装成web服务,提供Web API给Chatbot Server调用。

对于SDK服务,可以直接用pip安装SDK,pip install chatterbot。

对于web服务,chatterbot项目也有相关的开源的web服务封装实现,其中一个是基于django框架(https://github.com/gunthercox/django_chatterbot),还一个是基于flask框架(https://github.com/chamkank/flask-chatterbot)。

本例上文展示的代码采用了SDK本地调用的方式。

总之,利用开源的chatterbot项目,我们一行代码都不用写就可以实现系统中的Chatbot Engine。

微信公众号后台配置

本例采用了微信订阅号,登录后台开发者中心,可以配置服务端回调URL,用户消息和开发者需要的事件推送,将会被转发到该URL中。如下图所示配置:

图中的URL地址:http://longtailer.cn,就是Chatbot Server的域名地址,所以事先需要准备一个公网的服务器和域名。

运行效果展示

总结

本文是《实现微信聊天机器人》系列的初级篇,介绍了微信机器人的技术架构和实现框架,对于Chatbot Engine的实现原理没有详细说明,Chatbot Engine是聊天机器人的核心,它涉及到自然语言处理、机器学习的相关原理和算法。