auf NAS mit smb zugreifen

  • 15 Antworten
  • Letztes Antwortdatum
B

Braesident

Ambitioniertes Mitglied
1
Hallo Leute,

ich suche nach einem Weg wie ich
1) NAS geräte wie z.B. den USB-Stick an meinem Router anzeigen kann

2) Dateien auf meinem NAS speichern und laden kann
 
Hängt von Deinem NAS ab. Eine Möglichkeit wäre z.B. eine FTP - Verbindung.
 
Seit bitte so nett und schiebt meine Frage wieder zurück in die Developer-abteilung. Dort war meine Frage genau richtig.

entschuldigt das meine Fragestellung zu karg war.

Es geht um eine selbst erstellte App mit einer SQLite Datenbank die im moment im System gespeichert wird.
Die DB soll nun aber auf dem USB Stick an meiner Fritz Box gespeichert werden so das jeder Kolege auf Arbeit sich die Datenbank ziehen kann.

Das es irgend wie geht wissen wir ja. Es gibt ja einige Apps die nach dem Starten die Netzwerkresorcen und freigegenen Daten/Ordner von Computern anzeigen und mit einem Klick darauf zugreifen.
 
- Willst du immer die Datenbank-Datei kopieren oder reicht es dir, die Daten zu "spiegeln" (per Export/Import)?
- Wie groß wird die Datenbank? Gibt es dort regelmäßig viele Änderungen? Willst du immer die komplette Datei oder reichen nur "Änderungen"?
- Ist dein NAS ein "dummer Speicher" oder kann dort auch u.U. ein SQL-Server (z.B. MySQL) betrieben werden? Webserver (für z.B. Webservices)?
- Welche Übertragungsprotokolle werden von deinem NAS angeboten?
- Müssen Daten auch wieder zurück? Also vom Client auf dein NAS?


Wenn mich jetzt nicht alles täuscht, ist die Fritz!Box ein "dummer Speicher", der Zugriff per SMB/CIFS, HTTP(S) oder auch FTP(S) bereitstellen kann. Nicht ganz die ideale Lösung für die Verteilung von Daten einer Datenbank.
 
Also die DB beinhaltet hauptsächlich Adressen, Öffnungszeiten und Informationen zu einzelnen Ärzten.

Gedacht ist es so das die Kollegen morgens ihre DB im Büro aktualisieren, ggf. Informationen hinzufügen und zum Feierabend wieder synchronisieren.

Problem ist das halt kein richtiger Server vorhanden ist und auch nicht immer ein PC an ist, auf dem ein Server laufen könnte. Und ein Mietserver ist nicht gewünscht.
 
Braesident schrieb:
Gedacht ist es so das die Kollegen morgens ihre DB im Büro aktualisieren, ggf. Informationen hinzufügen und zum Feierabend wieder synchronisieren.
Spätestens hier ist aber eine Serverlogik notwendig, denn du kannst ja nicht einfach die Datei des Kollegen nehmen und die auf dem "Server" überschreiben. Was machst du, wenn zwei Kollegen Änderungen durchgeführt haben?

Im Prinzip reicht als Gegenstelle für dein Vorhaben ein Kleinstrechner (sogar ein Raspberry Pi) - ist eben abhängig, wie schnell und wie viele Kollegen (gleichzeitig) die Daten haben wollen.

EDIT: Gegenvorschlag:

Du legst die Liste in Google Docs (z.B. als Tabelle) auf deinem Google Drive an und gibst sie (auch zur Bearbeitung) für die Kollegen (per Google Accounts) frei. Die Informationen sollten nun nicht so komplex sein, dass sie den Rahmen einer einfahcen Tabelle sprengen (oder doch?). Die Kollegen können nun mit Google Tabelle darauf zugreifen und sie auch synchronisieren. Ebenso können sie aber auch das Ding bearbeiten.

Die Bearbeitung könnte dann sowohl vom Smartphone/Tablet erfolgen, als auch vom PC per Browser. Die Datei kannst du auch als Verknüpfung für den schnellen Aufruf auf einen der Homescreens legen.
 
Wie wär's mal, wenn Ihr daran denken würdet ein Service á la Google Docs für diese Aufgabe zu nutzen?
 
Erstmal vielen Dank für die schnellen Antworten.

Also nach Rücksprache wird Google Drive nicht gewünscht. Allerdings wird jetzt darüber nachgedacht, sich ein richtigen NAS zuzulegen. Bis dahin soll es so sein das die App der Mitarbeiter sich lediglich die DB von der Fritz Box laden kann.

Ich weiss schonmal das ich die Acces_wifi_state und warscheinlich die Storage Permission brauch :D

Wie kann ich jetzt den Server und die Daten finden?
 
Gibt es dafür auch Gründe?
Kämen denn evtl. andere Cloud-Dienste in Frage?

(Noch eine Idee, allerdings auch Google-Cloud: Theoretisch kann man das sogar allein über die Google Kontakte abbilden...)

Server finden: Über die IP-Adresse? Oder DNS-Namen? Von wo soll eigentlich auf die Daten zugegriffen werden? Lokales Netz? Aus dem Internet?
Daten finden: Wie stellst du dir denn den (bidirektionalen!) Datenaustausch vor? Welches Protokoll soll es denn sein?
 
Warum sie keine Cloud-Dienste nutzen möchten haben sie mir nicht gesagt. Aber ich nehme mal an, da auch Patienteninformationen in den Daten sein können.

Zugriff soll nur im lokalen Netzwerk stattfinden wie bei der (ohne schleichwerbung machen zu wollen) Fritz App Media.
Ich denke am sinvollsten wäre es den DNS-Namen zu verwenden.

Ansonsten kenn ich mich noch nicht so gut aus um sagen zu können welche Protokolle in Frage kämen bzw. ob und wie ein bidirektionaler Datenaustausch von nöten ist. Aber ich vermute nicht das beide Seiten gleichzeitig Senden und Empfangen müssen, Oder ?

Ich hatte mir das so gedacht:

> App scannt Netzwerk und sucht nach dem Servernamen der in den Appeinstellungen gespeichert werden kann
> wurde dieser gefunden wird die Datenbank-Datei von dem Pfad geladen, der ebenfalls in der App gespeichert wurde, und auf der SD oder dem Standartspeicher abgelegt
> und nun ließt meine App die DB aus

EDIT// Also, ich ging der Annahme das ich dafür upnp oder DLNA bräuchte was aber allem Anschein nach nur zum Medien streamen gedacht ist.
Das richtige Schlüsselwort scheint Samba(smb/jcifs) zu sein.
Hat jemand von euch Erfahrung damit. Ich suche gerade nach dem richtigen weg für die Importierung in meine App.
Warscheinlich müsste ich die entsprechenden Pakete von hier downloaden !? Und dann?
 
Zuletzt bearbeitet:
So leute, ich bin ein minimales Stückchen weiter gekommen.

Ich habe die jcifs in meine App integriert und vorerst in meiner MainActivity den Import 'jcifs.smb.*' eingefügt.
Hab einige Bsp-Codes getestet - ohne Erfolg. Jetzt versuche ich mich an einem Code der eine TXT-Datei auf meinem Fritz-NAS erstellen soll um zu sehen ob eine Verbindung zu stande kommt. Die Methode 'ProtectFolderTest' rufe ich gleich zu Anfang in der 'onCreate' auf.

Also meine App schmiert natürlich sofort ab. Und zwar an der Stelle: 'sfos = new SmbFileOutputStream(sFile); '
Mein Problem ist im Moment das ich keine SmbException bekomme.

Code:
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new ProtectFolderTest().main();

        // hier dann mein alter Code


    }

    public class ProtectFolderTest {

        private String USER_NAME = null;
        private String PASSWORD = null;
        private String DOMAIN = null;
        private String NETWORK_FOLDER = null;

        public void main() {
            Log.d(LOG_TAG, "ProtectFolderTest: -> main is called");
            try { String fileContent = "Hi, This is the SmbFile.";
                new ProtectFolderTest().copyFiles(fileContent, "SmbFile1.txt");

            } catch (Exception e) {
                System.err.println("Exception caught. Cause: " + e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/Main: -> Error -> Exception caught. Cause: " + e.getMessage());
            }
        }

        public boolean copyFiles(String fileContent, String fileName) {
            boolean successful = false;
            String path = null;
            NtlmPasswordAuthentication auth = null;
            SmbFile sFile = null;
            SmbFileOutputStream sfos = null;
            Log.d(LOG_TAG, "ProtectFolderTest: -> copyFiles is called");
            try {
                USER_NAME = "meinNutzerName";
                PASSWORD = "meinPasswort";
                DOMAIN = "IPmeinerFritzBox";
                NETWORK_FOLDER = "smb://IPmeinerFritzBox/FRITZ.NAS/Intenso-TwisterLine-01/";
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> pass-authentication");
                auth = new NtlmPasswordAuthentication(DOMAIN, USER_NAME, PASSWORD);
                path = NETWORK_FOLDER + fileName;
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> new smbfile");
                sFile = new SmbFile(path, auth);
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> new outputstream");             // <-- Dieser Log erscheint noch
                sfos = new SmbFileOutputStream(sFile);
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> write content");                   // <-- dieser nicht mehr
                sfos.write(fileContent.getBytes());
                successful = true;
                //System.out.println("File successfully created.");
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> File successfully created");
            } catch (SmbAuthException sae) {
                successful = false;
                //System.err.println("Unable to create file. Cause: " + e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + sae.getMessage());
            } catch (SmbException se) {
                successful = false;
                //System.err.println("Unable to create file. Cause: " + e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + se.getMessage());
            } catch (Exception e) {
                successful = false;
                //System.err.println("Unable to create file. Cause: " + e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + e.getMessage());
            }
            return successful;
        }
    }
 
Könntest du bitte die Fehlermeldung posten (logcat). Ich würde mal vermuten, dass sFile null ist.
 
10-18 15:51:14.034 21681-21681/? D/MainActivity﹕ ProtectFolderTest: -> main is called
10-18 15:51:14.034 21681-21681/? D/MainActivity﹕ ProtectFolderTest: -> copyFiles is called
10-18 15:51:14.034 21681-21681/? D/MainActivity﹕ ProtectFolderTest/copyFiles: -> pass-authentication
10-18 15:51:14.035 21681-21681/? D/MainActivity﹕ ProtectFolderTest/copyFiles: -> new smbfile
10-18 15:51:14.036 21681-21681/? D/MainActivity﹕ ProtectFolderTest/copyFiles: -> sFile >smb://192.168.178.1/FRITZ.NAS/Intenso-TwisterLine-01/SmbFile1.txt<
10-18 15:51:14.036 21681-21681/? D/MainActivity﹕ ProtectFolderTest/copyFiles: -> new outputstream

reicht diese gefilterte Liste oder soll ich meinen Filter noch ergänzen

übrigens als Permissions habe ich folgendes gesetzt:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 
Zuletzt bearbeitet:
Nein, die Liste reicht nicht, schließlich ist die auftretende Exception nicht aufgeführt. Ich wette aber, es handelt sich um eine NetworkOnMainThreadException

Lösung: Netzwerk-Kommunikation in einen eigenen Thread/Task auslagern.
 
Soo, ich hab mich jetzt damit mal ne Weile rumgeschlagen.
Zunächst einmal hat Thyrion recht, NetworkOnMainThreadException gab's bei mir direkt als erstes. Und wie er bereits schrieb, musst Du das in einen eigenen Task/Thread auslagern.
(Ich war dafür jetzt zu faul und hab die Prüfung abgeschaltet. Sehr unschöner Stil, ich weiß. Aber zum Testen reicht's.)

Abgesehen vom NetworkOnMainThread Problem, war dein Code eigentlich nahezu fertig.

Mein Hauptproblem war am Ende, dass ich immer eine SmbException mit "network name cannot be found" bekommen hab. Aus welchem Grund auch immer, kann ich mit jcifs nicht auf das NAS mit der IP .1 zugreifen, sondern muss stattdessen .254 verwenden. (Das kann aber auch ein spezifische Problem meiner FB (6490) sein, musste mal testen, welche IP bei dir geht.)

Lange Rede, kurzer Sinn. Das folgende funktioniert bei mir.

Javascript:
package com.example.jcifs;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbAuthException;
import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileOutputStream;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Workaroud NetworkOnMainThreadException, just for testing. NEED TO USE
        // ASYNC TASK!!
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        new ProtectFolderTest().main();

    }

    public class ProtectFolderTest {

        private String LOG_TAG = "";

        private String USER_NAME = null;
        private String PASSWORD = null;
        private String DOMAIN = null;
        private String NETWORK_FOLDER = null;

        public void main() {
            Log.d(LOG_TAG, "ProtectFolderTest: -> main is called");
            try {
                // Testcode for multiple runs
                DateFormat df = SimpleDateFormat.getDateTimeInstance();

                String fileContent = "Hi, This is the SmbFile AVM. " + df.format(new Date());
                new ProtectFolderTest().copyFiles(fileContent, "SmbFile1.txt");

            } catch (Exception e) {
                System.err.println("Exception caught. Cause: " + e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/Main: -> Error -> Exception caught. Cause: " + e.getMessage());
            }
        }

        public boolean copyFiles(String fileContent, String fileName) {
            boolean successful = false;

            String path = null;
            SmbFile sFile = null;
            SmbFileOutputStream sfos = null;

            Log.d(LOG_TAG, "ProtectFolderTest: -> copyFiles is called");
            try {
                USER_NAME = "test";
                PASSWORD = "hallo";
                DOMAIN = "192.168.1.254"; // FritzBox IP is .1, but Fritz.NAS is
                                          // .254 (at least in my setup?). Using
                                          // .1 gives an SmbException:
                                          // "network name cannot be found.".
                                          // Only .254 works.
                NETWORK_FOLDER = "smb://" + DOMAIN + "/FRITZ.NAS/test/";

                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> pass-authentication");
                final NtlmPasswordAuthentication AUTH = new NtlmPasswordAuthentication(DOMAIN, USER_NAME, PASSWORD);
                path = NETWORK_FOLDER + fileName;
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> new smbfile");
                sFile = new SmbFile(path, AUTH);
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> new outputstream"); // Dieser
                                                                                    // Log
                                                                                    // erscheint
                                                                                    // noch
                sfos = new SmbFileOutputStream(sFile);
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> write content"); // <--
                                                                                 // dieser
                                                                                 // nicht
                                                                                 // mehr
                sfos.write(fileContent.getBytes());

                // close stream
                sfos.close();

                successful = true;
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> File successfully created");
            } catch (SmbAuthException sae) {
                successful = false;
                // System.err.println("Unable to create file. Cause: " +
                // e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + sae.getMessage());
            } catch (SmbException se) {
                successful = false;
                // System.err.println("Unable to create file. Cause: " +
                // e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + se.getMessage());
            } catch (Exception e) {
                successful = false;
                // System.err.println("Unable to create file. Cause: " +
                // e.getMessage());
                Log.d(LOG_TAG, "ProtectFolderTest/copyFiles: -> Unable to create file. Cause: " + e.getMessage());
            }
            return successful;
        }
    }
}

Wie gesagt, läuft bei mir jetzt so. NetworkOnMainThread musst Du noch beheben (und dann natürlich das Strict rausnehmen) und rausfinden, welche IP/Pfad bei dir geht.

Ich hoffe Du kommst jetzt weiter. =)
 
  • Danke
Reaktionen: Braesident
Guten Morgen Leute

Vielen Dank reallord das du dir die Mühe gemacht hast. Es ist gut zu wissen das ich auf dem richtigen Weg bin.

Anfangs sah es ganz gut aus (beim aktuallisieren schmierte die App nicht ab. Aber eine Datei wurde leider nicht geschrieben. Nun schmiert meine App andauernt ab)
Jetzt muss ich aber mal fragen was ich in dem Filter der LogCat eintragen soll um die Fehlermeldungen zu bekommen. Ich hab jetzt schon alles mögliche probiert aber noch keine Smb Exception gesehen.

EDIT der Absturz kam durch einen Toast in der doInBackground Methode
Jetzt bekomme ich auch Fehlermeldungen je nach IP
mit .1 -> Timeout waiting for response from server: 0.0.0.0<00>/192.168.178.1
mit .254 -> Failed to negotiate

Ich benutze übrigens eine App aus dem Store (AndSMB) bei der das Problemlos funktioniert
dort habe ich beim Verbindung anlegen die 192.168.178.1 benutzt
END EDIT

EDIT 2 Jetzt geht es. Ich hatte noch nicht die richtige jcifs Version. Hab jetzt die 1.3.18 geladen.

Warscheinlich ist meine Anordnung einfach falsch.
Um die Übertragung auszuführen benutze ich ein SwipeRefresh im onCreate der MainActivity
Code:
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button btn_hinzu = (Button)findViewById(R.id.button_new_doc);
    btn_hinzu.setOnClickListener(this);

    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout_aktienliste);
    mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
  
        @Override
        public void onRefresh() {
          
            // Erzeugen einer Instanz von FileTaskFileTask fileTask = new FileTask();
            Log.d(LOG_TAG, "starte Thread");
            fileTask.execute();
        }
    });

    Log.d(LOG_TAG, "onCreate: -> dataSource = new DatenbankSource");
    dataSource = new DatenbankSource(this);
}

Die ProtectFolderTest Klasse hab ich als direkte Unterklasse belassen und rufe sie im FileTask auf.
Code:
public class FileTask extends AsyncTask<String, Integer, Boolean> {
  
    private final String LOG_TAG = FileTask.class.getSimpleName();
    @Override
    protected Boolean doInBackground(String... strings) {
      
        Log.d(LOG_TAG, "doInBackground");
        boolean ergebnis;
        ergebnis = false;

        new ProtectFolderTest().main();
        Log.d(LOG_TAG, "doInBackground after ProtectFolderTest");

        return ergebnis;
    }
  
    @Overrideprotected void onProgressUpdate(Integer... values) {
        //...
    }

    @Overrideprotected void onPostExecute(Boolean ergebnis) {
       
         Log.d(LOG_TAG, "onPostExecute");
         boolean dashier = ergebnis;
       
        Toast.makeText(MainActivity.this, "Datenbank geladen!",Toast.LENGTH_SHORT).show();
        mSwipeRefreshLayout.setRefreshing(false);
    }
}
 
Zuletzt bearbeitet:
Zurück
Oben Unten