如何从 android 程序上传 sqlite 数据库文件到 ftp 服务器

How to upload a sqlite db file to ftp server from android program

每次调用ftp写入操作时APP崩溃

我在 Fragment 中有以下 2 个方法。

public void uploadData () {     


        String domain = "10.142.42.10";  // <<< will it work as it is private ip?
        String user = "xxxx";
        String password = "xxxx";
        String serverRoad = "Documents";

        File file = new File("/sdcard/bluetooth/NRC_jiten.pdf");
        FTPClient ftp = new FTPClient();
        try {
            ftp.connect(InetAddress.getByName(domain));
            //ftp.connect(domain,21);
            ftp.login(user, password);

            ftp.changeWorkingDirectory(serverRoad);
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            FileInputStream is = new FileInputStream(file);
            BufferedInputStream buffIn = new BufferedInputStream(is);
            ftp.enterLocalPassiveMode();
            ftp.storeFile("jiten_pdf.pdf", buffIn);
            buffIn.close();

            ftp.logout();
            ftp.disconnect();
        } catch (Exception e) {
            Toast.makeText(getActivity(), "err:" + e,
                    Toast.LENGTH_SHORT).show();
        }
}

public void uploadFileBackground () {

        new Thread(new Runnable() {
            public void run() {

                uploadData();

            }
        }).start();


    }

现在,从 Activity 我在鼠标单击按钮时触发 uploadFileBackground

代码有问题吗?我已经提到了这个网站,但未能成功。

TIA。


LogCat

            08-25 19:00:56.042  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.044  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.047  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.047  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.049  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.050  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.051  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.052  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.052  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.056  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.056  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.058  16119-16119/com.sbordolo.potholefinder W/GooglePlayServicesUtil﹕ Google Play services out of date.  Requires 7571000 but found 6774470
08-25 19:00:56.079  16119-16138/com.sbordolo.potholefinder D/OpenGLRenderer﹕ Use EGL_SWAP_BEHAVIOR_PRESERVED: true
08-25 19:00:56.080  16119-16119/com.sbordolo.potholefinder D/﹕ HostConnection::get() New Host Connection established 0xb3ffc140, tid 16119
08-25 19:00:56.088  16119-16119/com.sbordolo.potholefinder D/Atlas﹕ Validating map...
08-25 19:00:56.474  16119-16138/com.sbordolo.potholefinder D/﹕ HostConnection::get() New Host Connection established 0xb3ffc3c0, tid 16138
08-25 19:00:56.483  16119-16138/com.sbordolo.potholefinder I/OpenGLRenderer﹕ Initialized EGL, version 1.4
08-25 19:00:56.488  16119-16138/com.sbordolo.potholefinder D/OpenGLRenderer﹕ Enabling debug mode 0
08-25 19:00:56.514  16119-16138/com.sbordolo.potholefinder W/EGL_emulation﹕ eglSurfaceAttrib not implemented
08-25 19:00:56.514  16119-16138/com.sbordolo.potholefinder W/OpenGLRenderer﹕ Failed to set EGL_SWAP_BEHAVIOR on surface 0xb3fdb4e0, error=EGL_SUCCESS
08-25 19:00:56.844  16119-16119/com.sbordolo.potholefinder E/WindowManager﹕ android.view.WindowLeaked: Activity com.sbordolo.potholefinder.HomeScreen has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{9052cc6 V.E..... R....... 0,0-1026,591} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
            at android.app.Dialog.show(Dialog.java:298)
            at com.sbordolo.potholefinder.CoordinateClass.isGooglePlayServicesAvailable(CoordinateClass.java:110)
            at com.sbordolo.potholefinder.CoordinateClass.onActivityCreated(CoordinateClass.java:66)
            at android.app.Fragment.performActivityCreated(Fragment.java:2061)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:912)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
            at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
            at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1869)
            at android.app.Activity.performCreateCommon(Activity.java:5985)
            at android.app.Activity.performCreate(Activity.java:5992)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
            at android.app.ActivityThread.access0(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5257)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

首先,使用 Google Play 应用更新您的 Google Play 服务。如您所见:

Google Play services out of date.

它已经过时了。

其次,不要使用 Thread 这样的方式在 Android 上做背景工作,因为

(...) it violates the second rule of the single-threaded model: do not access the Android UI toolkit from outside the UI thread.

尝试使用AsyncTask, Service, or Handler.

有关线程的更多信息 here, on services here, and on Handler here


现在针对你的问题,你得到了这个异常:

android.view.WindowLeaked: Activity com.sbordolo.potholefinder.HomeScreen has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{9052cc6 V.E..... R....... 0,0-1026,591} that was originally added here

最常抛出 WindowLeaked 异常的原因是代码中未消除 Dialog

并且您的 logcat 跟踪显示一个对话框正试图弹出:

at android.app.Dialog.show(Dialog.java:298)

编辑: 所以它因为你的 Toast 而崩溃。删除它,或者尝试上面的解决方案,你应该没问题。

第二次编辑: 正如您提到的,为了让答案完整,您的 ftp 服务器需要设置正确的权限,以便您的程序可以编写里面的东西您的 chmod 777 可以工作,但是 小心 ,因为它会让您的服务器保持开放状态,任何人都可以在那里写入。

我找到了根本原因,我在查看 pcap 文件时发现存在权限问题。 FTP 登录成功,但在客户端尝试放入文件时,由于权限问题,失败了!将目录权限设为777,修复!

感谢 Mauker 帮助我解决这个问题。

谢谢。

这是我为我的应用程序实现的代码。

public static String getDiretorioBackup() {

    String diretorio = "";
    if (android.os.Build.VERSION.SDK_INT >= 23) {
        diretorio = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + "/" + "dir";
    }
    else {
        diretorio = Environment.getExternalStorageDirectory() + "/" + "dir";    
    }

    return diretorio;
}


public static FTPClient connnectFTP(String ip, String userName, String pass) throws Exception{   

        FTPClient mFtpClient = new FTPClient();  
        mFtpClient.setConnectTimeout(10 * 1000);
        mFtpClient.connect( ip );

        boolean status = mFtpClient.login(userName, pass);  
        Log.e("login ftp:", String.valueOf(status));  

        return mFtpClient;
    } 


public static Boolean uploadFile(String email, String pathUpload, String guidStr) throws Exception
    {  
        FTPClient ftpClient = connnectFTP(Constantes.FTP, Constantes.FTP_USER, Constantes.FTP_PASS);

        if(ftpClient != null)
        {                   
            FileInputStream srcFileStream = new FileInputStream( getDiretorioBackup() +"/"+ ConstantesBanco.DATABASE_NAME ); //antes de fazer o ftp é feita a cópia local  
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileTransferMode(ftpClient.BINARY_FILE_TYPE);
            ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE);


            boolean status = ftpClient.storeFile( pathUpload+fileName , srcFileStream);

            Log.d(TAG, String.valueOf(status) + "- reply code:"+ ftpClient.getReplyCode()+" "+ftpClient.getReplyString());  
            srcFileStream.close();
            ftpClient.disconnect();

            return status;
        }
        else{
            throw new BackupFtpException(Constantes.ERRO_SERV_FTP);         
        }
    }